[#13] simplified ivago controller module
parent
edc3605770
commit
4950c3660e
|
@ -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<Vec<Street>, FejError> {
|
||||
let client = reqwest::Client::new();
|
||||
let response = client.get(SEARCH_URL).query(&[("q", street_name)]).send()?;
|
||||
let data: Vec<HashMap<String, String>> = 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<Tz>,
|
||||
end_date: &DateTime<Tz>,
|
||||
) -> Result<Vec<PickupTime>, 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<HashMap<String, String>> = response.json()?;
|
||||
|
||||
let mut output: Vec<PickupTime> = 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)
|
||||
}
|
||||
|
|
|
@ -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<Tz>,
|
||||
end_date: &DateTime<Tz>,
|
||||
) -> Result<Vec<PickupTime>, 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<HashMap<String, String>> = response.json()?;
|
||||
|
||||
let mut output: Vec<PickupTime> = 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)
|
||||
}
|
|
@ -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<Vec<Street>, FejError> {
|
||||
let client = reqwest::Client::new();
|
||||
let response = client.get(SEARCH_URL).query(&[("q", street_name)]).send()?;
|
||||
let data: Vec<HashMap<String, String>> = 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())
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue