97 lines
2.8 KiB
Rust
97 lines
2.8 KiB
Rust
use reqwest::Url;
|
|
use serde::Deserialize;
|
|
|
|
use crate::bahn_api::{basic_types::station_ids::StationId, transport_modes::TransportMode};
|
|
|
|
use super::{
|
|
basic_types::station_ids::{DbStopId, NamedStation, StationEvaNumber, StationIdRef},
|
|
transport_modes::TransportModesSet,
|
|
};
|
|
|
|
pub async fn query_stations(query: &str) -> Result<QueriedStations, QueryStationsError> {
|
|
let response = reqwest::get(
|
|
Url::parse_with_params(
|
|
"https://www.bahn.de/web/api/reiseloesung/orte",
|
|
[("suchbegriff", query), ("typ", "ALL"), ("limit", "10")],
|
|
)
|
|
.expect("hardcoded url and bahn.de-provided route id should always be valid"),
|
|
)
|
|
.await
|
|
.map_err(QueryStationsError::NetworkError)?
|
|
.error_for_status()
|
|
.map_err(QueryStationsError::NetworkError)?
|
|
.text()
|
|
.await
|
|
.map_err(QueryStationsError::NetworkError)?;
|
|
|
|
let data: QSData = serde_json::from_str(&response)
|
|
.map_err(move |e| QueryStationsError::ParseError(response, e))?;
|
|
|
|
type QSData = Vec<QSStation>;
|
|
|
|
#[derive(Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct QSStation {
|
|
#[serde(default)]
|
|
ext_id: Option<String>,
|
|
#[serde(default)]
|
|
id: Option<String>,
|
|
name: String,
|
|
#[serde(default)]
|
|
lat: Option<f64>,
|
|
#[serde(default)]
|
|
lon: Option<f64>,
|
|
#[serde(default)]
|
|
products: Vec<String>,
|
|
}
|
|
|
|
Ok(QueriedStations {
|
|
stations: data
|
|
.into_iter()
|
|
.filter_map(|station| {
|
|
Some(QueriedStation {
|
|
station: NamedStation {
|
|
name: station.name,
|
|
id: StationId {
|
|
eva_number: StationEvaNumber(station.ext_id?),
|
|
db_station_id: DbStopId(station.id?),
|
|
},
|
|
},
|
|
lat_lon: station
|
|
.lat
|
|
.and_then(|lat| station.lon.map(|lon| (lat, lon))),
|
|
transport_modes: station
|
|
.products
|
|
.iter()
|
|
.filter_map(|v| TransportMode::from_str_from_bahn_api(v))
|
|
.fold(TransportModesSet::new(), |set, v| set.with(v)),
|
|
})
|
|
})
|
|
.collect(),
|
|
})
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct QueriedStations {
|
|
pub stations: Vec<QueriedStation>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct QueriedStation {
|
|
pub station: NamedStation,
|
|
pub lat_lon: Option<(f64, f64)>,
|
|
pub transport_modes: TransportModesSet,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum QueryStationsError {
|
|
NetworkError(reqwest::Error),
|
|
ParseError(String, serde_json::Error),
|
|
}
|
|
|
|
impl<'a> From<&'a QueriedStation> for StationIdRef<'a> {
|
|
fn from(value: &'a QueriedStation) -> Self {
|
|
From::from(&value.station)
|
|
}
|
|
}
|