From 0f87ca8b1392eec7a307ac9d8219228cb6b5e88c Mon Sep 17 00:00:00 2001 From: Denys Konovalov Date: Wed, 3 Nov 2021 17:43:20 +0100 Subject: [PATCH] added endpoint for tomorrow timetable --- src/indiware_connector.rs | 197 +++++++++++++++++++++++++++++++++++++- src/main.rs | 23 ++++- 2 files changed, 218 insertions(+), 2 deletions(-) diff --git a/src/indiware_connector.rs b/src/indiware_connector.rs index 1cdb777..7704150 100644 --- a/src/indiware_connector.rs +++ b/src/indiware_connector.rs @@ -1,7 +1,7 @@ use crate::config; use crate::schema::timetable; use crate::DbConn; -use chrono::Local; +use chrono::{Duration, Local}; use diesel::{Insertable, Queryable}; use quickxml_to_serde::{xml_string_to_json, Config}; use serde_derive::{Deserialize, Serialize}; @@ -48,6 +48,24 @@ async fn get_today_timetable_xml() -> serde_json::value::Value { xml_string_to_json(resp, &Config::new_with_defaults()).unwrap() } +async fn get_tomorrow_timetable_xml() -> serde_json::value::Value { + let client = reqwest::Client::new(); + let resp = client + .get(format!( + "{}/PlanKl{}.xml", + config::TIMETABLE_URL, + (Local::today() + Duration::days(1)).format("%Y%m%d") + )) + .basic_auth(config::TIMETABLE_USER, config::TIMETABLE_PASSWORD) + .send() + .await + .unwrap() + .text() + .await + .unwrap(); + xml_string_to_json(resp, &Config::new_with_defaults()).unwrap() +} + async fn get_timetable_xml() -> serde_json::value::Value { let client = reqwest::Client::new(); let resp = client @@ -78,6 +96,22 @@ async fn get_today_timetable_xml_data() -> Vec { classes.to_owned() } +async fn get_tomorrow_timetable_xml_data() -> Vec { + let xml = get_tomorrow_timetable_xml().await; + let classes = xml + .as_object() + .unwrap() + .get("VpMobil") + .unwrap() + .get("Klassen") + .unwrap() + .get("Kl") + .unwrap() + .as_array() + .unwrap(); + classes.to_owned() +} + async fn get_timetable_xml_data() -> Vec { let xml = get_timetable_xml().await; let classes = xml @@ -187,6 +221,99 @@ pub async fn get_today_timetable(_conn: DbConn) -> Vec { timetable } +pub async fn get_tomorrow_timetable(_conn: DbConn) -> Vec { + let xml = get_tomorrow_timetable_xml().await; + let classes = get_tomorrow_timetable_xml_data().await; + let mut timetable: Vec = Vec::new(); + for i in classes.iter() { + let mut courses: Vec = Vec::new(); + let nothing = json!([""]); + let std = i + .as_object() + .unwrap() + .get("Pl") + .unwrap() + .as_object() + .unwrap() + .get("Std") + .unwrap_or(¬hing); + let mut plan = vec![]; + if std.is_array() { + plan.extend(std.as_array().unwrap().iter().cloned()) + } else if std.is_object() { + plan.push(std.clone()) + } + for i in &plan { + if i.as_object() != None { + courses.push(i.to_owned()); + } else { + dbg!("Failed: {:?}", &i); + } + } + let empty_list = serde_json::Value::Array(vec![]); + let empty_obj = serde_json::Value::Object(Map::new()); + let empty_vec = Vec::new(); + let info_list = xml + .as_object() + .unwrap() + .get("VpMobil") + .unwrap() + .get("ZusatzInfo") + .unwrap_or(&empty_obj) + .get("ZiZeile") + .unwrap_or(&empty_list) + .as_array() + .unwrap_or(&empty_vec); + let mut info = String::new(); + for item in info_list { + info.push_str(item.as_str().unwrap_or("\r\n")); + info.push_str("\r\n"); + } + let response = TimetableData { + count: plan.len(), + courses, + info, + }; + let timetable_element = Timetable { + date: String::from( + xml.as_object() + .unwrap() + .get("VpMobil") + .unwrap() + .get("Kopf") + .unwrap() + .get("DatumPlan") + .unwrap() + .as_str() + .unwrap(), + ), + updated: String::from( + xml.as_object() + .unwrap() + .get("VpMobil") + .unwrap() + .get("Kopf") + .unwrap() + .get("zeitstempel") + .unwrap() + .as_str() + .unwrap(), + ), + class: String::from( + i.as_object() + .unwrap() + .get("Kurz") + .unwrap() + .as_str() + .unwrap(), + ), + timetable_data: serde_json::from_str(&json!(response).to_string()).unwrap(), + }; + timetable.push(timetable_element) + } + timetable +} + pub async fn get_timetable(_conn: DbConn) -> Vec { let xml = get_timetable_xml().await; let classes = get_timetable_xml_data().await; @@ -348,6 +475,74 @@ pub async fn get_today_class_timetable(_conn: DbConn, class: String) -> Timetabl response } +pub async fn get_tomorrow_class_timetable(_conn: DbConn, class: String) -> TimetableData { + let xml = get_tomorrow_timetable_xml().await; + let classes = get_tomorrow_timetable_xml_data().await; + let courses: Vec = Vec::new(); + let empty_list = serde_json::Value::Array(vec![]); + let empty_obj = serde_json::Value::Object(Map::new()); + let empty_vec = Vec::new(); + let info_list = xml + .as_object() + .unwrap() + .get("VpMobil") + .unwrap() + .get("ZusatzInfo") + .unwrap_or(&empty_obj) + .get("ZiZeile") + .unwrap_or(&empty_list) + .as_array() + .unwrap_or(&empty_vec); + let mut info = String::new(); + for item in info_list { + info.push_str(item.as_str().unwrap_or("\r\n")); + info.push_str("\r\n"); + } + let mut response = TimetableData { + count: 0, + courses, + info, + }; + for i in classes.iter() { + if i.as_object() + .unwrap() + .get("Kurz") + .unwrap() + .as_str() + .unwrap() + .replace("/", "_") + == class + { + let nothing = json!([""]); + let std = i + .as_object() + .unwrap() + .get("Pl") + .unwrap() + .as_object() + .unwrap() + .get("Std") + .unwrap_or(¬hing); + let mut plan = vec![]; + if std.is_array() { + plan.extend(std.as_array().unwrap().iter().cloned()) + } else if std.is_object() { + plan.push(std.clone()) + } + response.count = plan.len(); + for i in plan { + if i.as_object() != None { + response.courses.push(i.to_owned()); + } else { + dbg!("Failed: {:?}", &i); + } + } + break; + } + } + response +} + pub async fn get_class_timetable(_conn: DbConn, class: String) -> TimetableData { let xml = get_timetable_xml().await; let classes = get_timetable_xml_data().await; diff --git a/src/main.rs b/src/main.rs index 03fc33d..51f53f2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -180,6 +180,15 @@ async fn get_today_timetable( Json::from(timetable) } +#[get("/tomorrow")] +async fn get_tomorrow_timetable( + conn: DbConn, + _key: ApiKey<'_>, +) -> Json> { + let timetable = timetable_connector::get_tomorrow_timetable(conn).await; + Json::from(timetable) +} + #[get("/")] async fn get_class_timetable( conn: DbConn, @@ -200,6 +209,16 @@ async fn get_today_class_timetable( Json::from(timetable) } +#[get("//tomorrow")] +async fn get_tomorrow_class_timetable( + conn: DbConn, + class: String, + _key: ApiKey<'_>, +) -> Json { + let timetable = timetable_connector::get_tomorrow_class_timetable(conn, class).await; + Json::from(timetable) +} + #[get("/")] async fn get_classes(_key: ApiKey<'_>) -> Json> { let class_list = timetable_connector::get_classes().await; @@ -227,7 +246,9 @@ fn rocket() -> _ { get_timetable, get_class_timetable, get_today_timetable, - get_today_class_timetable + get_today_class_timetable, + get_tomorrow_timetable, + get_tomorrow_class_timetable ], ) .mount("/api/classes", routes![get_classes])