From daed8fee5871ae7e2aab8a5a79d73cd2964bd42b Mon Sep 17 00:00:00 2001 From: "Dr. Matthias Ratajczak" Date: Thu, 22 Dec 2022 15:15:03 +0100 Subject: [PATCH] add response structs --- Cargo.lock | 211 +++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 6 +- src/main.rs | 1 + src/response.rs | 99 +++++++++++++++++++++++ 4 files changed, 313 insertions(+), 4 deletions(-) create mode 100644 src/response.rs diff --git a/Cargo.lock b/Cargo.lock index 6d16910..84cfc84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.68" @@ -50,18 +59,47 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "num-integer", + "num-traits", + "serde", + "winapi", +] + [[package]] name = "chunked_transfer" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "convert_case" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "cssparser" version = "0.27.2" @@ -70,7 +108,7 @@ checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" dependencies = [ "cssparser-macros", "dtoa-short", - "itoa", + "itoa 0.4.8", "matches", "phf 0.8.0", "proc-macro2", @@ -89,12 +127,60 @@ dependencies = [ "syn", ] +[[package]] +name = "cxx" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "departure" version = "0.1.0" dependencies = [ "anyhow", + "chrono", "scraper", + "serde", + "serde_derive", + "serde_json", "ureq", ] @@ -196,6 +282,30 @@ dependencies = [ "syn", ] +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "idna" version = "0.3.0" @@ -212,6 +322,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + [[package]] name = "js-sys" version = "0.3.60" @@ -223,9 +339,18 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.138" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] [[package]] name = "lock_api" @@ -284,6 +409,25 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.16.0" @@ -573,6 +717,12 @@ dependencies = [ "webpki", ] +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + [[package]] name = "scopeguard" version = "1.1.0" @@ -594,6 +744,12 @@ dependencies = [ "tendril", ] +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + [[package]] name = "sct" version = "0.7.0" @@ -635,6 +791,31 @@ name = "serde" version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +dependencies = [ + "itoa 1.0.5", + "ryu", + "serde", +] [[package]] name = "servo_arc" @@ -718,6 +899,15 @@ dependencies = [ "utf-8", ] +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thin-slice" version = "0.1.1" @@ -760,6 +950,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "untrusted" version = "0.7.1" @@ -910,6 +1106,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 71a103c..020dcd5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,12 @@ edition = "2021" [dependencies] scraper = { version = "*", default-features = false } -anyhow = { version = "*", default-features = false } +anyhow = { version = "*"} ureq = { version = "*", default-features = false , features = ["tls"]} +chrono = {version = "0.4.23", default-features = false, features = ["clock", "serde", "std"]} +serde = {version = "1.0.151", features = ["derive"]} +serde_derive = "1.0.151" +serde_json = "1.0.91" [profile.release] strip = true diff --git a/src/main.rs b/src/main.rs index 8314150..6a101a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod extractor; mod query; +mod response; use anyhow::Result; use scraper::Html; diff --git a/src/response.rs b/src/response.rs new file mode 100644 index 0000000..9495ec4 --- /dev/null +++ b/src/response.rs @@ -0,0 +1,99 @@ +#![allow(dead_code)] + +use std::fmt::Debug; + +use anyhow::Result; +use chrono::{DateTime, Local, TimeZone, Utc}; +use serde::{de, Deserialize, Deserializer}; + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct Departure { + id: String, + dl_id: String, + line_name: String, + direction: String, + platform: Platform, + mot: String, + #[serde(default, deserialize_with = "deserialize_realtime")] + real_time: Option>, + #[serde(deserialize_with = "deserialize_timestamp")] + scheduled_time: DateTime, + state: Option, + route_changes: Vec, + diva: Diva, + cancel_reasons: Vec, +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct Platform { + name: String, + #[serde(rename = "Type")] + type_: String, +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct RouteChange { + // fields omitted +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct Diva { + number: String, + network: String, +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct CancelReason { + // fields omitted +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct Response { + name: String, + status: Status, + place: String, + expiration_time: String, + departures: Vec, +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct Status { + code: String, +} + +/// Deserialize a timestamp in the form of '/Date(1671713820000-0000)/' +fn deserialize_timestamp<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + let timestamp: i64 = s + .trim_start_matches("/Date(") + .trim_end_matches(")/") + .split('-') + .next() + .ok_or_else(|| de::Error::custom("Invalid timestamp format"))? + .parse() + .map_err(de::Error::custom)?; + let result = Utc.timestamp_millis_opt(timestamp).unwrap(); + + let local_tz = chrono::offset::Local::now().timezone(); + Ok(result.with_timezone(&local_tz)) +} + +fn deserialize_realtime<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + match deserialize_timestamp(deserializer) { + Ok(inner) => Ok(Some(inner)), + Err(_) => Ok(None), + } +}