Flesh out api and add tests
This commit is contained in:
parent
e47099f492
commit
24cf670465
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
/target
|
||||
.env
|
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -107,6 +107,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
@ -1093,9 +1094,21 @@ dependencies = [
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.1"
|
||||
|
@ -10,4 +10,5 @@ reqwest = { version = "0.12.15", features = ["json"] }
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.140"
|
||||
thiserror = "2.0.12"
|
||||
tokio = { version = "1.44.2", features = ["macros", "rt"] }
|
||||
url = "2.5.4"
|
||||
|
76
src/lib.rs
76
src/lib.rs
@ -1,6 +1,9 @@
|
||||
use crate::models::Response;
|
||||
use crate::models::eta::{EtaRequest, EtaResp};
|
||||
use crate::models::follow::{FollowRequest, FollowResp};
|
||||
use crate::models::route::{RouteRequest, RouteResp};
|
||||
use reqwest::{Client, Url};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
pub mod models;
|
||||
@ -32,18 +35,19 @@ impl CTAClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn fetch_route(&mut self, route: &str) -> Result<RouteResp, Error> {
|
||||
let req = RouteRequest {
|
||||
rt: route.to_string(),
|
||||
key: self.key.clone(),
|
||||
};
|
||||
pub async fn make_request<T: Serialize, V: for<'a> Deserialize<'a>>(
|
||||
&mut self,
|
||||
endpoint: &str,
|
||||
req: T,
|
||||
) -> Result<V, Error> {
|
||||
let url = self.url.join(endpoint)?;
|
||||
|
||||
let url = self.url.join("ttpositions.aspx")?;
|
||||
let resp: Response<RouteResp> = self
|
||||
let resp: Response<V> = self
|
||||
.client
|
||||
.get(url)
|
||||
.query(&req)
|
||||
.query(&[("outputType", "JSON")])
|
||||
.query(&[("key", &self.key)])
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
@ -51,4 +55,62 @@ impl CTAClient {
|
||||
|
||||
Ok(resp.ctatt)
|
||||
}
|
||||
|
||||
pub async fn fetch_route(&mut self, route: &str) -> Result<RouteResp, Error> {
|
||||
let req = RouteRequest {
|
||||
rt: route.to_string(),
|
||||
};
|
||||
|
||||
self.make_request("ttpositions.aspx", req).await
|
||||
}
|
||||
|
||||
pub async fn fetch_eta(&mut self, eta_request: EtaRequest) -> Result<EtaResp, Error> {
|
||||
self.make_request("ttarrivals.aspx", eta_request).await
|
||||
}
|
||||
|
||||
pub async fn fetch_train_schedule(&mut self, run_number: u32) -> Result<FollowResp, Error> {
|
||||
self.make_request("ttfollow.aspx", FollowRequest { run_number })
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::CTAClient;
|
||||
use crate::models::eta::EtaRequest;
|
||||
|
||||
pub fn client() -> CTAClient {
|
||||
let token = std::env::var("CTA_TOKEN").expect("Missing CTA_TOKEN");
|
||||
|
||||
CTAClient::new(token)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_fetch_eta() {
|
||||
let mut client = client();
|
||||
|
||||
let _eta = client
|
||||
.fetch_eta(EtaRequest {
|
||||
mapid: None,
|
||||
stpid: Some(30111),
|
||||
max: Some(1),
|
||||
rt: None,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_fetch_route() {
|
||||
let mut client = client();
|
||||
|
||||
let _eta = client.fetch_route("blue").await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_fetch_train_schedule() {
|
||||
let mut client = client();
|
||||
|
||||
let _train = client.fetch_train_schedule(109).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
50
src/models/eta.rs
Normal file
50
src/models/eta.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use crate::models::Ctatt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct EtaRequest {
|
||||
pub mapid: Option<u32>,
|
||||
pub stpid: Option<u32>,
|
||||
pub max: Option<u32>,
|
||||
pub rt: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct EtaResp {
|
||||
#[serde(flatten)]
|
||||
pub header: Ctatt,
|
||||
pub eta: Vec<Eta>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Eta {
|
||||
#[serde(rename = "staId")]
|
||||
pub sta_id: String,
|
||||
#[serde(rename = "stpId")]
|
||||
pub stp_id: String,
|
||||
#[serde(rename = "staNm")]
|
||||
pub sta_nm: String,
|
||||
#[serde(rename = "stpDe")]
|
||||
pub stp_de: String,
|
||||
pub rn: String,
|
||||
pub rt: String,
|
||||
#[serde(rename = "destSt")]
|
||||
pub dest_st: String,
|
||||
#[serde(rename = "destNm")]
|
||||
pub tr_dr: String,
|
||||
pub prdt: String,
|
||||
#[serde(rename = "arrT")]
|
||||
pub arr_t: String,
|
||||
#[serde(rename = "isApp")]
|
||||
pub is_app: String,
|
||||
#[serde(rename = "isSch")]
|
||||
pub is_sch: String,
|
||||
#[serde(rename = "isDly")]
|
||||
pub is_dly: String,
|
||||
#[serde(rename = "isFlt")]
|
||||
pub is_flt: String,
|
||||
pub flags: Option<String>,
|
||||
pub lat: String,
|
||||
pub lon: String,
|
||||
pub heading: String,
|
||||
}
|
53
src/models/follow.rs
Normal file
53
src/models/follow.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use crate::models::Ctatt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct FollowRequest {
|
||||
#[serde(rename = "runnumber")]
|
||||
pub run_number: u32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Position {
|
||||
pub lat: String,
|
||||
pub lon: String,
|
||||
pub heading: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct ScheduledStop {
|
||||
#[serde(rename = "staId")]
|
||||
pub sta_id: String,
|
||||
#[serde(rename = "stpId")]
|
||||
pub stp_id: String,
|
||||
#[serde(rename = "staNm")]
|
||||
pub sta_nm: String,
|
||||
#[serde(rename = "stpDe")]
|
||||
pub stp_de: String,
|
||||
pub rn: String,
|
||||
pub rt: String,
|
||||
#[serde(rename = "destSt")]
|
||||
pub dest_st: String,
|
||||
#[serde(rename = "destNm")]
|
||||
pub tr_dr: String,
|
||||
pub prdt: String,
|
||||
#[serde(rename = "arrT")]
|
||||
pub arr_t: String,
|
||||
#[serde(rename = "isApp")]
|
||||
pub is_app: String,
|
||||
#[serde(rename = "isSch")]
|
||||
pub is_sch: String,
|
||||
#[serde(rename = "isDly")]
|
||||
pub is_dly: String,
|
||||
#[serde(rename = "isFlt")]
|
||||
pub is_flt: String,
|
||||
pub flags: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct FollowResp {
|
||||
#[serde(flatten)]
|
||||
pub header: Ctatt,
|
||||
pub position: Position,
|
||||
pub eta: Vec<ScheduledStop>,
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
pub mod eta;
|
||||
pub mod follow;
|
||||
pub mod route;
|
||||
pub mod train;
|
||||
|
||||
|
@ -5,7 +5,6 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct RouteRequest {
|
||||
pub rt: String,
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user