From 8a553f2ebfec4c379b64112ae75c63c3044d72c6 Mon Sep 17 00:00:00 2001 From: Mariano Riefolo Date: Sat, 31 Aug 2024 18:06:28 +0200 Subject: [PATCH] feat(api): add api endpoint to retrieve classes for a given teacher --- Cargo.lock | 209 ++++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 2 + src/api/mod.rs | 85 +++++++++++++++++++- 3 files changed, 283 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ad8e6f3..c70ddc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,7 +38,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.76", ] [[package]] @@ -135,6 +135,15 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -184,6 +193,25 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpufeatures" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "cssparser" version = "0.31.2" @@ -204,7 +232,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn", + "syn 2.0.76", +] + +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", ] [[package]] @@ -215,7 +264,17 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.76", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", ] [[package]] @@ -264,6 +323,28 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + [[package]] name = "fastrand" version = "2.1.1" @@ -325,6 +406,23 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + [[package]] name = "futures-sink" version = "0.3.30" @@ -344,9 +442,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", + "futures-io", + "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -358,6 +461,16 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getopts" version = "0.2.21" @@ -415,6 +528,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "html5ever" version = "0.27.0" @@ -426,7 +545,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn", + "syn 2.0.76", ] [[package]] @@ -738,7 +857,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.76", ] [[package]] @@ -764,9 +883,14 @@ name = "orario-scolastico-itet" version = "0.1.0" dependencies = [ "axum", + "csv", + "failure", + "hex", "reqwest", "scraper", + "serde", "serde_json", + "sha1", "tokio", ] @@ -868,7 +992,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn", + "syn 2.0.76", ] [[package]] @@ -906,7 +1030,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.76", ] [[package]] @@ -1034,10 +1158,12 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", + "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", "windows-registry", ] @@ -1218,7 +1344,7 @@ checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.76", ] [[package]] @@ -1264,6 +1390,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1354,6 +1491,17 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.76" @@ -1380,6 +1528,18 @@ dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + [[package]] name = "system-configuration" version = "0.6.1" @@ -1466,7 +1626,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.76", ] [[package]] @@ -1557,6 +1717,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-bidi" version = "0.3.15" @@ -1584,6 +1750,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "unicode-xid" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" + [[package]] name = "untrusted" version = "0.9.0" @@ -1656,7 +1828,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.76", "wasm-bindgen-shared", ] @@ -1690,7 +1862,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.76", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1701,6 +1873,19 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +[[package]] +name = "wasm-streams" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.70" @@ -1841,7 +2026,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.76", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 86badb2..c157f05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,10 +5,12 @@ edition = "2021" [dependencies] axum = "0.7.5" +csv = "1.3.0" failure = "0.1.8" hex = "0.4.3" reqwest = { version = "0.12.7", features = ["stream"] } scraper = "0.20.0" +serde = { version = "1.0.209", features = ["derive"] } serde_json = "1.0.127" sha1 = "0.10.6" tokio = { version = "1.40.0", features = ["full"] } diff --git a/src/api/mod.rs b/src/api/mod.rs index c51eee2..7a5971d 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,17 +1,27 @@ use axum::{ + extract::Query, http::StatusCode, response::{IntoResponse, Json}, routing::get, Router, }; +use csv::StringRecord; use failure::Error; use scraper::{Html, Selector}; +use serde::Deserialize; use serde_json::json; use sha1::{Digest, Sha1}; +use std::collections::HashMap; +use std::ops::Range; use std::{fs, process::Command}; pub fn get_routes() -> Router { - Router::new().nest("/api", Router::new().route("/pdf", get(pdf))) + Router::new().nest( + "/api", + Router::new() + .route("/pdf", get(pdf)) + .route("/classi", get(get_classes)), + ) } async fn get_pdf_links() -> Result, reqwest::Error> { @@ -68,3 +78,76 @@ async fn download_pdf(id: u8) -> Result { Ok(csv_path) } + +#[derive(Deserialize)] +pub struct FilterByTeacherQuery { + id: u8, + professore: String, +} + +pub struct Header { + teacher: u8, + weekdays: HashMap>, +} + +pub async fn get_classes(Query(params): Query) -> impl IntoResponse { + let filename = download_pdf(params.id).await.unwrap(); + 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()); + + for record in rdr.records() { + let record = record.unwrap(); + if record[header.teacher as usize] == params.professore { + let mut result: HashMap> = HashMap::new(); + for (i, cell) in record.iter().enumerate() { + for (j, range) in header.weekdays.clone() { + if range.contains(&i) { + result.entry(j).or_default().push(cell); + } + } + } + return (StatusCode::OK, Json(json!(result))); + } + } + + ( + StatusCode::UNPROCESSABLE_ENTITY, + Json(json!({ "errore": "professore non trovato"})), + ) +} + +pub fn get_header(record: &StringRecord) -> Header { + let mut docente: u8 = 0; + let mut weekdays = HashMap::new(); + + for (i, field) in record.iter().enumerate() { + let next_index = record + .iter() + .skip(i + 1) + .position(|x| !x.is_empty()) + .unwrap_or(record.len()); + + if field == "DOCENTE" { + docente = i as u8; + } else if field == "LUNEDI" { + weekdays.insert("Lunedì".to_string(), i..next_index + i + 1); + } else if field == "MARTEDI" { + weekdays.insert("Martedì".to_string(), i..next_index + i + 1); + } else if field == "MERCOLEDI" { + weekdays.insert("Mercoledì".to_string(), i..next_index + i + 1); + } else if field == "GIOVEDI" { + weekdays.insert("Giovedì".to_string(), i..next_index + i + 1); + } else if field == "VENERDI" { + weekdays.insert("Venerdì".to_string(), i..next_index + i + 1); + } else if field == "SABATO" { + weekdays.insert("Sabato".to_string(), i..next_index + i + 1); + } + } + + Header { + teacher: docente, + weekdays, + } +}