diff --git a/Makefile b/Makefile index 69f4a4a..76b08f0 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ -IMAGE := rust-api:latest +IMAGE := chewingbever/fej +TAG := 0.1-dev shell := /bin/bash @@ -15,9 +16,12 @@ release: .PHONY: release image: Dockerfile - @ docker build -t '$(IMAGE)' . + @ docker build -t '$(IMAGE):$(TAG)' . .PHONY: image +push: image + @ docker push '$(IMAGE):$(TAG)' +.PHONY: push # Run run: diff --git a/src/ivago/controller/mod.rs b/src/ivago/controller/mod.rs index 382d3b3..01f00a4 100644 --- a/src/ivago/controller/mod.rs +++ b/src/ivago/controller/mod.rs @@ -1,89 +1,41 @@ -use reqwest::blocking as reqwest; -use std::collections::HashMap; -use std::convert::{TryFrom, From}; -use rocket::http::Status; -use std::error::Error; - -pub mod structs; -use structs::{Street, Date, PickupTime}; +mod search; +pub use search::{Street, search_streets}; -/// The base URL where their API starts -const BASE_URL: &str = "https://www.ivago.be/nl/particulier/afval/ophaling"; -const SEARCH_URL: &str ="https://www.ivago.be/nl/particulier/autocomplete/garbage/streets"; +///// Return the known pickup times for the given street and/or city +///// +///// # Arguments +///// +///// * `street` - name of the street +///// * `city` - city the street is in +//pub fn get_pickup_times(street: Street, number: u32) -> Result, Box> { +// // The client needs to store cookies for the requests to work +// let client = reqwest::Client::builder().cookie_store(true).build()?; +// // Create post data +// let form = [ +// ("garbage_type", ""), +// ("ivago_street", String::from(street).as_str()), +// ("number", format!("{}", number).as_str()), +// ("form_id", "garbage_address_form"), +// ]; -impl From for String { - fn from(street: Street) -> String { - format!("{} ({})", street.name, street.city) - } -} +// // This request just serves to populate the cookies +// client.post(BASE_URL) +// .form(&form) +// .send()?; - -/// Searches the Ivago API for streets in the given city -/// -/// # Arguments -/// -/// * `street` - name of the street -/// * `city` - city the street is in -// TODO find out how to do this async -pub fn search_streets(street_name: &String) -> Result, Box> { - let client = reqwest::Client::new(); - let response = client.get(SEARCH_URL) - .query(&[("q", street_name)]) - .send()?; - let data: Vec> = response.json()?; - - let mut output: Vec = Vec::new(); - - // We iterate over every item and extract the needed data - for map in data.iter() { - if let Some(value) = map.get("value") { - match Street::try_from(*value) { - Ok(street) => output.push(street), - Err(_) => continue, - } - } - } - - Ok(output) -} - - -/// Return the known pickup times for the given street and/or city -/// -/// # Arguments -/// -/// * `street` - name of the street -/// * `city` - city the street is in -pub fn get_pickup_times(street: Street, number: u32) -> Result, Box> { - // The client needs to store cookies for the requests to work - let client = reqwest::Client::builder().cookie_store(true).build()?; - - // Create post data - let form = [ - ("garbage_type", ""), - ("ivago_street", String::from(street).as_str()), - ("number", format!("{}", number).as_str()), - ("form_id", "garbage_address_form"), - ]; - - // This request just serves to populate the cookies - client.post(BASE_URL) - .form(&form) - .send()?; - - let params = [ - ("_format", "json"), - ("type", ""), +// let params = [ +// ("_format", "json"), +// ("type", ""), - ] +// ] -r2 = s.get("https://www.ivago.be/nl/particulier/garbage/pick-up/pickups?", - params={ - "_format": "json", - "type": "", - "start": "1622332800", - "end": "163861328100" - } -} +//r2 = s.get("https://www.ivago.be/nl/particulier/garbage/pick-up/pickups?", +// params={ +// "_format": "json", +// "type": "", +// "start": "1622332800", +// "end": "163861328100" +// } +//} diff --git a/src/ivago/controller/pickup_times.rs b/src/ivago/controller/pickup_times.rs new file mode 100644 index 0000000..98b8e64 --- /dev/null +++ b/src/ivago/controller/pickup_times.rs @@ -0,0 +1,19 @@ +const BASE_URL: &str = "https://www.ivago.be/nl/particulier/afval/ophaling"; + + +/// Represents a timezoneless date +pub struct Date { + day: u8, + month: u8, + year: u32, +} + + +/// Represents a pickup time instance. All fields are a direct map of the +/// original API +pub struct PickupTime { + date: Date, + label: String, + classes: Vec, + url: String +} diff --git a/src/ivago/controller/search.rs b/src/ivago/controller/search.rs new file mode 100644 index 0000000..d0282de --- /dev/null +++ b/src/ivago/controller/search.rs @@ -0,0 +1,83 @@ +use reqwest::blocking as reqwest; +use std::collections::HashMap; +use std::convert::TryFrom; +use serde::ser::{Serialize, Serializer, SerializeStruct}; +use std::error::Error; + + +/// Endpoint for the search feature +const SEARCH_URL: &str ="https://www.ivago.be/nl/particulier/autocomplete/garbage/streets"; + + +impl From for String { + fn from(street: Street) -> String { + format!("{} ({})", street.name, street.city) + } +} + + +impl Serialize for Street { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut s = serializer.serialize_struct("Street", 2)?; + s.serialize_field("name", &self.name)?; + s.serialize_field("city", &self.city)?; + s.end() + } +} + + +impl TryFrom for Street { + type Error = (); + + fn try_from(value: String) -> Result { + if let Some(index) = value.find('(') { + Ok(Street { + name: (value[0 .. index - 1].trim()).to_string(), + city: (value[index + 1 .. value.len() - 1].trim()).to_string(), + }) + + }else { + Err(()) + } + } +} + + +/// Represents a street +pub struct Street { + pub name: String, + pub city: String, +} + + +/// Searches the Ivago API for streets in the given city +/// +/// # Arguments +/// +/// * `street` - name of the street +/// * `city` - city the street is in +// TODO find out how to do this async +pub fn search_streets(street_name: &String) -> Result, Box> { + let client = reqwest::Client::new(); + let response = client.get(SEARCH_URL) + .query(&[("q", street_name)]) + .send()?; + let data: Vec> = response.json()?; + + let mut output: Vec = Vec::new(); + + // We iterate over every item and extract the needed data + for map in data.iter() { + if let Some(value) = map.get("value") { + match Street::try_from(value.clone()) { + Ok(street) => output.push(street), + Err(_) => continue, + } + } + } + + Ok(output) +} diff --git a/src/ivago/controller/structs.rs b/src/ivago/controller/structs.rs deleted file mode 100644 index a5931d2..0000000 --- a/src/ivago/controller/structs.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::convert::TryFrom; -use serde::ser::{Serialize, Serializer, SerializeStruct}; - - -/// Represents a street -pub struct Street { - pub name: String, - pub city: String, -} - -impl Serialize for Street { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut s = serializer.serialize_struct("Street", 2)?; - s.serialize_field("name", &self.name)?; - s.serialize_field("city", &self.city)?; - s.end() - } -} - -impl TryFrom for Street { - type Error = (); - - fn try_from(value: String) -> Result { - if let Some(index) = value.find('(') { - Ok(Street { - name: (value[0 .. index - 1].trim()).to_string(), - city: (value[index + 1 .. value.len() - 1].trim()).to_string(), - }) - - }else { - Err(()) - } - } -} - - -/// Represents a timezoneless date -pub struct Date { - day: u8, - month: u8, - year: u32, -} - - -/// Represents a pickup time instance. All fields are a direct map of the -/// original API -pub struct PickupTime { - date: Date, - label: String, - classes: Vec, - url: String -} diff --git a/src/ivago/mod.rs b/src/ivago/mod.rs index f597494..7ba799e 100644 --- a/src/ivago/mod.rs +++ b/src/ivago/mod.rs @@ -1,14 +1,11 @@ #[cfg(test)] mod tests; +mod controller; use rocket_contrib::json::Json; -mod controller; -use controller as ctrl; -use ctrl::structs::Street; - pub fn routes() -> Vec { routes![ - search_streets, + search_streets_json, ] } @@ -16,8 +13,8 @@ pub fn routes() -> Vec { // TODO make this async // TODO change this so it can return errors instead of empty json #[get("/search?", format="json")] -pub fn search_streets(street: String) -> Json> { - match ctrl::search_streets(&street) { +pub fn search_streets_json(street: String) -> Json> { + match controller::search_streets(&street) { Ok(streets) => Json(streets), Err(err) => { println!("{:?}", err);