72 lines
2.6 KiB
Rust
72 lines
2.6 KiB
Rust
use chrono::DateTime;
|
|
use url::Url;
|
|
use urlencoding::encode;
|
|
use crate::error::train_order_api_error::ResolveTripNumberError;
|
|
use crate::model::db_vendo_navigator_api::TrainOrdering;
|
|
use crate::model::travelynx::TrainType;
|
|
|
|
pub async fn get_railcar_identifier_by_journey(
|
|
train_type: TrainType,
|
|
trip_number: usize,
|
|
station_uic: usize,
|
|
departure_time: usize
|
|
) -> Result<u64, ResolveTripNumberError> {
|
|
let train_ordering = query_train_order_api(train_type, trip_number, station_uic, departure_time).await?;
|
|
println!("Received train ordering response {:?}", train_ordering);
|
|
find_railcar_identifier(train_ordering)
|
|
}
|
|
|
|
fn find_railcar_identifier(train_ordering: TrainOrdering) -> Result<u64, ResolveTripNumberError> {
|
|
//TODO: refactor - trainsets can consist out of several trains
|
|
let trainset = train_ordering.train_sets.first()
|
|
.ok_or(ResolveTripNumberError::Api("No items in field 'fahrzeuggruppe'".to_string()))?;
|
|
let identifier_str = trainset.identifier.to_owned();
|
|
let train_type = &trainset.journey.train_type;
|
|
let identifier = crop_first_n_chars(identifier_str.as_str(), train_type.to_string().len())
|
|
.to_string().parse::<u64>()?;
|
|
Ok(identifier)
|
|
}
|
|
|
|
async fn query_train_order_api(
|
|
train_type: TrainType,
|
|
trip_number: usize,
|
|
station_uic: usize,
|
|
departure_time: usize
|
|
) -> reqwest::Result<TrainOrdering> {
|
|
println!("Resolving trip {train_type} {trip_number} from {station_uic} at {departure_time}");
|
|
let client = reqwest::ClientBuilder::new()
|
|
.build()?;
|
|
let api_url = build_api_url(train_type, trip_number, station_uic, departure_time);
|
|
println!("Fetching {api_url}");
|
|
client.get(api_url)
|
|
.header("Accept", "application/x.db.vendo.mob.wagenreihung.v3+json")
|
|
.header("X-Correlation-ID", "ABCDE")
|
|
.send()
|
|
.await?
|
|
.json::<TrainOrdering>()
|
|
.await
|
|
}
|
|
|
|
fn build_api_url(
|
|
train_type: TrainType,
|
|
trip_number: usize,
|
|
station_uic: usize,
|
|
departure_time: usize
|
|
) -> Url {
|
|
let train_trip = format!("{}_{}", train_type.to_string(), trip_number);
|
|
let departure = DateTime::from_timestamp(departure_time as i64, 0)
|
|
.expect("invalid departure time");
|
|
Url::parse(format!(
|
|
"https://app.vendo.noncd.db.de/mob/zuglaeufe/{}/halte/by-abfahrt/{}_{}/wagenreihung",
|
|
train_trip,
|
|
station_uic,
|
|
encode(departure.to_rfc3339().as_str())
|
|
).as_str()).unwrap()
|
|
}
|
|
|
|
fn crop_first_n_chars(s: &str, count: usize) -> &str {
|
|
match s.char_indices().skip(count).next() {
|
|
Some((pos, _)) => &s[pos..],
|
|
None => ""
|
|
}
|
|
} |