Files
ice-bingo/src/api/db_vendo_navigator.rs

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 => ""
}
}