feat: add logic for journey->train identifier resolving, add recording of journeys, build api bearer auth
This commit is contained in:
71
src/api/db_vendo_navigator.rs
Normal file
71
src/api/db_vendo_navigator.rs
Normal file
@ -0,0 +1,71 @@
|
||||
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> {
|
||||
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 => ""
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user