feat: make reservation api wrapper

dev
Jef Roosens 2023-05-11 15:49:05 +02:00
parent 0aa021259a
commit c799d3d226
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
7 changed files with 76 additions and 21 deletions

2
Cargo.lock generated
View File

@ -46,6 +46,7 @@ dependencies = [
"affluences-api", "affluences-api",
"chrono", "chrono",
"tokio", "tokio",
"uuid",
] ]
[[package]] [[package]]
@ -82,6 +83,7 @@ dependencies = [
"js-sys", "js-sys",
"num-integer", "num-integer",
"num-traits", "num-traits",
"serde",
"time", "time",
"wasm-bindgen", "wasm-bindgen",
"winapi", "winapi",

View File

@ -24,3 +24,17 @@ https://api.affluences.com/app/v3/sites
body: {"selected_categories":[1],"page":0,"search_query":"university of ghent"} body: {"selected_categories":[1],"page":0,"search_query":"university of ghent"}
zoek op alle mogelijke bibs, met een search query zoek op alle mogelijke bibs, met een search query
Reservatie maken: posten naar url van deze vorm
98403 is de resource id van het lokaal, verkregen via de "available" call
https://reservation.affluences.com/api/reserve/98403
reservation request type
{"auth_type":null,"email":"dink.dink@ugent.be","date":"2023-05-11","start_time":"17:00","end_time":"18:00","note":"imagine","user_firstname":"dink","user_lastname":"dink","user_phone":null,"person_count":1}
reservation response success
{"reservation_id":33071685,"auth_token":null,"user_validation":true,"ticket_payload":null,"email":"dink.dink@ugent.be","success":"reservation_confirm_request_send","successMessage":"You are almost there… For your reservation to be effective, you must confirm it from the email we have just sent you. As a reminder, the email address you used is","cancellation_token":null}

View File

@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
chrono = "0.4.24" chrono = { version = "0.4.24", features = ["serde"] }
reqwest = { version = "0.11.17", features = ["json"] } reqwest = { version = "0.11.17", features = ["json"] }
serde = { version = "1.0.163", features = ["derive"] } serde = { version = "1.0.163", features = ["derive"] }
uuid = { version = "1.3.2", features = ["serde"] } uuid = { version = "1.3.2", features = ["serde"] }

View File

@ -1,7 +1,7 @@
mod models; mod models;
use chrono::NaiveDate; use chrono::{NaiveDate, NaiveDateTime};
use models::{Resource, Data, SiteData}; use models::{Resource, Data, SiteData, Reservation, ReservationResponse};
const USER_AGENT: &str = "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/112.0"; const USER_AGENT: &str = "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/112.0";
@ -17,13 +17,18 @@ impl AffluencesClient {
} }
} }
pub async fn available(&mut self, resource_uuid: &str, date: NaiveDate, resource_type: u32) -> reqwest::Result<Vec<Resource>> { pub async fn available(&mut self, site_id: uuid::Uuid, date: NaiveDate, resource_type: u32) -> reqwest::Result<Vec<Resource>> {
let url = format!("https://reservation.affluences.com/api/resources/{}/available", resource_uuid); let url = format!("https://reservation.affluences.com/api/resources/{}/available", site_id);
self.client.get(url).query(&[("date", date.format("%Y-%m-%d").to_string()), ("type", resource_type.to_string())]).send().await?.json::<Vec<Resource>>().await self.client.get(url).query(&[("date", date.format("%Y-%m-%d").to_string()), ("type", resource_type.to_string())]).send().await?.json::<Vec<Resource>>().await
} }
pub async fn site_data(&mut self, name: &str) -> reqwest::Result<SiteData> { pub async fn site_data(&mut self, slug: &str) -> reqwest::Result<SiteData> {
let url = format!("https://api.affluences.com/app/v3/sites/{}", name); let url = format!("https://api.affluences.com/app/v3/sites/{}", slug);
Ok(self.client.get(url).send().await?.json::<Data<SiteData>>().await?.data) Ok(self.client.get(url).send().await?.json::<Data<SiteData>>().await?.data)
} }
pub async fn make_reservation(&mut self, resource_id: u64, reservation: &Reservation) -> reqwest::Result<ReservationResponse> {
let url = format!("https://reservation.affluences.com/api/reserve/{}", resource_id);
self.client.get(url).json(reservation).send().await?.json::<ReservationResponse>().await
}
} }

View File

@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use chrono::{NaiveTime, NaiveDate};
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct Hour { pub struct Hour {
@ -82,8 +83,8 @@ pub struct SiteDataForecast {
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct SiteDataNotice { pub struct SiteDataNotice {
message: String, pub message: String,
url: Option<String> pub url: Option<String>
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
@ -138,7 +139,7 @@ pub struct SiteDataStatus {
pub struct SiteData { pub struct SiteData {
pub id: uuid::Uuid, pub id: uuid::Uuid,
pub slug: String, pub slug: String,
parent: Option<String>, pub parent: Option<String>,
pub primary_name: String, pub primary_name: String,
pub secondary_name: String, pub secondary_name: String,
pub concat_name: String, pub concat_name: String,
@ -148,7 +149,7 @@ pub struct SiteData {
pub phone_number: Option<String>, pub phone_number: Option<String>,
pub email: Option<String>, pub email: Option<String>,
pub url: Option<String>, pub url: Option<String>,
notices: Vec<SiteDataNotice>, pub notices: Vec<SiteDataNotice>,
// messages // messages
pub estimated_distance: f64, pub estimated_distance: f64,
pub current_forecast: SiteDataForecast, pub current_forecast: SiteDataForecast,
@ -166,6 +167,37 @@ pub struct SiteData {
pub extended_forecasts: bool, pub extended_forecasts: bool,
pub booking_url: Option<String>, pub booking_url: Option<String>,
pub validated: bool, pub validated: bool,
pub validationStatus: String, #[serde(rename = "validationStatus")]
pub publicationStatus: String pub validation_status: String,
#[serde(rename = "publicationStatus")]
pub publication_status: String
}
#[derive(Serialize, Debug)]
pub struct Reservation {
// This string might not be correct
pub auth_type: Option<String>,
pub email: String,
pub date: NaiveDate,
pub start_time: String,
pub end_time: String,
pub note: String,
pub user_firstname: String,
pub user_lastname: String,
pub user_phone: Option<String>,
pub person_count: u64
}
#[derive(Deserialize, Debug)]
pub struct ReservationResponse {
pub reservation_id: u64,
// This string might not be correct
pub auth_type: Option<String>,
pub user_validation: bool,
// ticket_payload
pub email: String,
pub success: String,
#[serde(rename = "successMessage")]
pub success_message: String,
// cancellation_token
} }

View File

@ -9,3 +9,4 @@ edition = "2021"
affluences-api = { path = "../affluences-api" } affluences-api = { path = "../affluences-api" }
tokio = { version = "1.28.1", features = ["full"] } tokio = { version = "1.28.1", features = ["full"] }
chrono = "*" chrono = "*"
uuid = "*"

View File

@ -1,17 +1,18 @@
use affluences_api::AffluencesClient; use affluences_api::AffluencesClient;
use chrono::NaiveDate; use chrono::NaiveDate;
use uuid::{uuid, Uuid};
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let site = "ghent-university"; let site = "faculty-library-sciences";
let id: Uuid = uuid!("4737e57a-ee05-4f7b-901a-7bb541eeb297");
// let uuid = "026b8caa-d310-464f-b714-4c21a2cf98ea";
let mut client = AffluencesClient::new(); let mut client = AffluencesClient::new();
let res = client.site_data(site).await.unwrap();
// let res = client // let res = client.site_data(site).await.unwrap();
// .available(uuid, NaiveDate::from_ymd_opt(2023, 5, 11).unwrap(), 1)
// .await let res = client
// .unwrap(); .available(id, NaiveDate::from_ymd_opt(2023, 5, 11).unwrap(), 1)
.await
.unwrap();
println!("{:?}", res); println!("{:?}", res);
} }