feat(api): add api endpoints to retrieve every teacher and class
This commit is contained in:
parent
8d1fe3b8f2
commit
d3d9f04a2c
113
src/api/mod.rs
113
src/api/mod.rs
@ -11,7 +11,7 @@ use scraper::{Html, Selector};
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use sha1::{Digest, Sha1};
|
use sha1::{Digest, Sha1};
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::{fs, process::Command};
|
use std::{fs, process::Command};
|
||||||
|
|
||||||
@ -21,7 +21,9 @@ pub fn get_routes() -> Router {
|
|||||||
Router::new()
|
Router::new()
|
||||||
.route("/pdf", get(pdf))
|
.route("/pdf", get(pdf))
|
||||||
.route("/classi", get(get_classes))
|
.route("/classi", get(get_classes))
|
||||||
.route("/professori", get(get_teachers)),
|
.route("/professori", get(get_teachers))
|
||||||
|
.route("/classe", get(get_class))
|
||||||
|
.route("/professore", get(get_teacher)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +96,7 @@ pub struct Header {
|
|||||||
weekdays: HashMap<String, Range<usize>>,
|
weekdays: HashMap<String, Range<usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_classes(Query(params): Query<FilterByTeacherQuery>) -> impl IntoResponse {
|
pub async fn get_class(Query(params): Query<FilterByTeacherQuery>) -> impl IntoResponse {
|
||||||
let filename = match download_pdf(params.id).await {
|
let filename = match download_pdf(params.id).await {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
@ -136,7 +138,7 @@ pub struct FilterByClassQuery {
|
|||||||
classe: String,
|
classe: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_teachers(Query(params): Query<FilterByClassQuery>) -> impl IntoResponse {
|
pub async fn get_teacher(Query(params): Query<FilterByClassQuery>) -> impl IntoResponse {
|
||||||
let filename = match download_pdf(params.id).await {
|
let filename = match download_pdf(params.id).await {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
@ -222,3 +224,106 @@ pub fn get_header(record: &StringRecord) -> Header {
|
|||||||
weekdays,
|
weekdays,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct GetTeachersQuery {
|
||||||
|
id: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_teachers(Query(params): Query<GetTeachersQuery>) -> impl IntoResponse {
|
||||||
|
let filename = match download_pdf(params.id).await {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(_) => {
|
||||||
|
return (
|
||||||
|
StatusCode::UNPROCESSABLE_ENTITY,
|
||||||
|
Json(json!({ "errore": "ID non valido"})),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let csv_content = fs::read_to_string(&filename).unwrap();
|
||||||
|
let mut rdr = csv::Reader::from_reader(csv_content.as_bytes());
|
||||||
|
let header = get_header(rdr.headers().unwrap());
|
||||||
|
|
||||||
|
let mut teachers = Vec::new();
|
||||||
|
|
||||||
|
for record in rdr.records() {
|
||||||
|
let record = match record {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(_) => {
|
||||||
|
return (
|
||||||
|
StatusCode::UNPROCESSABLE_ENTITY,
|
||||||
|
Json(json!({ "errore": "Formato non supportato"})),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(teacher) = record.get(header.teacher as usize) {
|
||||||
|
if !teacher.is_empty() {
|
||||||
|
teachers.push(teacher.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !teachers.is_empty() {
|
||||||
|
(StatusCode::OK, Json(json!(teachers)))
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
StatusCode::UNPROCESSABLE_ENTITY,
|
||||||
|
Json(json!({ "errore": "classe non trovata"})),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct GetClassesQuery {
|
||||||
|
id: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid_class(class: &str) -> bool {
|
||||||
|
class.len() == 5
|
||||||
|
&& class.chars().next().unwrap().is_digit(6)
|
||||||
|
&& class.chars().skip(1).all(|x| x.is_alphabetic())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_classes(Query(params): Query<GetClassesQuery>) -> impl IntoResponse {
|
||||||
|
let filename = match download_pdf(params.id).await {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(_) => {
|
||||||
|
return (
|
||||||
|
StatusCode::UNPROCESSABLE_ENTITY,
|
||||||
|
Json(json!({ "errore": "ID non valido"})),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let csv_content = fs::read_to_string(&filename).unwrap();
|
||||||
|
|
||||||
|
let mut rdr = csv::Reader::from_reader(csv_content.as_bytes());
|
||||||
|
let header = get_header(rdr.headers().unwrap());
|
||||||
|
|
||||||
|
let mut classes: Vec<HashMap<char, HashSet<String>>> = vec![HashMap::new(); 5];
|
||||||
|
|
||||||
|
for record in rdr.records() {
|
||||||
|
let record = record.unwrap();
|
||||||
|
for (i, cell) in record.iter().enumerate() {
|
||||||
|
for (_, range) in header.weekdays.clone() {
|
||||||
|
if range.contains(&i) && is_valid_class(cell) {
|
||||||
|
let value = classes
|
||||||
|
[cell.chars().next().unwrap().to_digit(6).unwrap() as usize - 1usize]
|
||||||
|
.entry(cell.chars().nth(1).unwrap())
|
||||||
|
.or_default();
|
||||||
|
value.insert(cell[2..].to_string().to_lowercase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if classes.is_empty() {
|
||||||
|
(
|
||||||
|
StatusCode::UNPROCESSABLE_ENTITY,
|
||||||
|
Json(json!({ "errore": "classe non trovata"})),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(StatusCode::OK, Json(json!(classes)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user