diff --git a/src/ivago/controller/structs/basic_date.rs b/src/ivago/controller/basic_date.rs similarity index 100% rename from src/ivago/controller/structs/basic_date.rs rename to src/ivago/controller/basic_date.rs diff --git a/src/ivago/controller/mod.rs b/src/ivago/controller/mod.rs index fddd7e4..0084a3d 100644 --- a/src/ivago/controller/mod.rs +++ b/src/ivago/controller/mod.rs @@ -1,6 +1,96 @@ -mod pickup_times; -mod search; -pub mod structs; +use crate::errors::FejError; +use chrono::DateTime; +use chrono_tz::Tz; +use reqwest::blocking as reqwest; +use std::collections::HashMap; +use std::convert::{From, TryFrom}; -pub use pickup_times::get_pickup_times; -pub use search::search_streets; +mod basic_date; +mod pickup_time; +mod street; + +pub use basic_date::BasicDate; +pub use pickup_time::PickupTime; +pub use street::Street; + +/// Endpoint for the search feature +const SEARCH_URL: &str = "https://www.ivago.be/nl/particulier/autocomplete/garbage/streets"; +/// Endpoint for populating the initial cookies +const BASE_URL: &str = "https://www.ivago.be/nl/particulier/afval/ophaling"; +/// Endpoint for the actual calendar output +const CAL_URL: &str = "https://www.ivago.be/nl/particulier/garbage/pick-up/pickups"; + +/// Searches the Ivago API for streets in the given city +/// +/// # Arguments +/// +/// * `street` - name of the street +/// * `city` - city the street is in +pub fn search_streets(street_name: &str) -> Result, FejError> { + let client = reqwest::Client::new(); + let response = client.get(SEARCH_URL).query(&[("q", street_name)]).send()?; + let data: Vec> = response.json()?; + + // This is pretty cool, filter_map first does get() on all the maps, and + // then filters out any None values + // Then, we do the same thing for streets + Ok(data + .iter() + .filter_map(|m| m.get("value")) + .filter_map(|v| Street::try_from(v.as_str()).ok()) + .collect()) +} + +/// Returns the pickup times for the various trash types +/// +/// # Arguments +/// +/// * `street` - desired street +/// * `number` - house number +/// * `start_date` - earliest date for the results +/// * `end_date` - latest date for the results +pub fn get_pickup_times( + street: &Street, + number: &u32, + start_date: &DateTime, + end_date: &DateTime, +) -> Result, FejError> { + let client = reqwest::Client::builder().cookie_store(true).build()?; + + // This populates the cookies with the necessary values + client + .post(BASE_URL) + .form(&[ + ("garbage_type", ""), + ("ivago_street", &String::from(street)), + ("number", &number.to_string()), + ("form_id", "garbage_address_form"), + ]) + .send()?; + + let response = client + .get(CAL_URL) + .query(&[ + ("_format", "json"), + ("type", ""), + ("start", &start_date.timestamp().to_string()), + ("end", &end_date.timestamp().to_string()), + ]) + .send()?; + let data: Vec> = response.json()?; + + let mut output: Vec = Vec::new(); + + for map in data + .iter() + .filter(|m| m.contains_key("date") && m.contains_key("label")) + { + // Because we filtered the maps in the loop, we can safely use unwrap + // here + if let Ok(date) = BasicDate::try_from(map.get("date").unwrap().as_str()) { + output.push(PickupTime::new(date, map.get("label").unwrap().to_string())) + } + } + + Ok(output) +} diff --git a/src/ivago/controller/structs/pickup_time.rs b/src/ivago/controller/pickup_time.rs similarity index 100% rename from src/ivago/controller/structs/pickup_time.rs rename to src/ivago/controller/pickup_time.rs diff --git a/src/ivago/controller/pickup_times.rs b/src/ivago/controller/pickup_times.rs deleted file mode 100644 index 95d080c..0000000 --- a/src/ivago/controller/pickup_times.rs +++ /dev/null @@ -1,56 +0,0 @@ -use super::structs::{BasicDate, PickupTime, Street}; -use crate::errors::FejError; -use chrono::DateTime; -use chrono_tz::Tz; -use reqwest::blocking as reqwest; -use std::collections::HashMap; -use std::convert::{From, TryFrom}; - -const BASE_URL: &str = "https://www.ivago.be/nl/particulier/afval/ophaling"; -const CAL_URL: &str = "https://www.ivago.be/nl/particulier/garbage/pick-up/pickups"; - -pub fn get_pickup_times( - street: &Street, - number: &u32, - start_date: &DateTime, - end_date: &DateTime, -) -> Result, FejError> { - let client = reqwest::Client::builder().cookie_store(true).build()?; - - // This populates the cookies with the necessary values - client - .post(BASE_URL) - .form(&[ - ("garbage_type", ""), - ("ivago_street", &String::from(street)), - ("number", &number.to_string()), - ("form_id", "garbage_address_form"), - ]) - .send()?; - - let response = client - .get(CAL_URL) - .query(&[ - ("_format", "json"), - ("type", ""), - ("start", &start_date.timestamp().to_string()), - ("end", &end_date.timestamp().to_string()), - ]) - .send()?; - let data: Vec> = response.json()?; - - let mut output: Vec = Vec::new(); - - for map in data - .iter() - .filter(|m| m.contains_key("date") && m.contains_key("label")) - { - // Because we filtered the maps in the loop, we can safely use unwrap - // here - if let Ok(date) = BasicDate::try_from(map.get("date").unwrap().as_str()) { - output.push(PickupTime::new(date, map.get("label").unwrap().to_string())) - } - } - - Ok(output) -} diff --git a/src/ivago/controller/search.rs b/src/ivago/controller/search.rs deleted file mode 100644 index e66652d..0000000 --- a/src/ivago/controller/search.rs +++ /dev/null @@ -1,29 +0,0 @@ -use super::structs::Street; -use crate::errors::FejError; -use reqwest::blocking as reqwest; -use std::collections::HashMap; -use std::convert::TryFrom; - -/// Endpoint for the search feature -const SEARCH_URL: &str = "https://www.ivago.be/nl/particulier/autocomplete/garbage/streets"; - -/// Searches the Ivago API for streets in the given city -/// -/// # Arguments -/// -/// * `street` - name of the street -/// * `city` - city the street is in -pub fn search_streets(street_name: &str) -> Result, FejError> { - let client = reqwest::Client::new(); - let response = client.get(SEARCH_URL).query(&[("q", street_name)]).send()?; - let data: Vec> = response.json()?; - - // This is pretty cool, filter_map first does get() on all the maps, and - // then filters out any None values - // Then, we do the same thing for streets - Ok(data - .iter() - .filter_map(|m| m.get("value")) - .filter_map(|v| Street::try_from(v.as_str()).ok()) - .collect()) -} diff --git a/src/ivago/controller/structs/street.rs b/src/ivago/controller/street.rs similarity index 100% rename from src/ivago/controller/structs/street.rs rename to src/ivago/controller/street.rs diff --git a/src/ivago/controller/structs/mod.rs b/src/ivago/controller/structs/mod.rs deleted file mode 100644 index ed6cf3c..0000000 --- a/src/ivago/controller/structs/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod basic_date; -mod pickup_time; -mod street; - -pub use basic_date::BasicDate; -pub use pickup_time::PickupTime; -pub use street::Street; diff --git a/src/ivago/mod.rs b/src/ivago/mod.rs index 28ac98b..e4d1037 100644 --- a/src/ivago/mod.rs +++ b/src/ivago/mod.rs @@ -1,7 +1,7 @@ mod controller; -use controller::structs::{BasicDate, PickupTime, Street}; use controller::{get_pickup_times, search_streets}; +use controller::{BasicDate, PickupTime, Street}; use rocket::http::Status; use rocket_contrib::json::Json;