add point finder from args
This commit is contained in:
+10
@@ -0,0 +1,10 @@
|
||||
use std::env::args;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
pub fn get_station_name_from_args() -> Result<String> {
|
||||
args()
|
||||
.into_iter()
|
||||
.nth(1)
|
||||
.context("getting station name from args")
|
||||
}
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
mod args;
|
||||
mod query;
|
||||
pub mod response;
|
||||
|
||||
pub use query::query_server;
|
||||
pub use args::get_station_name_from_args;
|
||||
pub use query::get_departures_for_station;
|
||||
pub use response::format_departures;
|
||||
|
||||
+3
-2
@@ -1,9 +1,10 @@
|
||||
use anyhow::Result;
|
||||
|
||||
use departure::{format_departures, query_server};
|
||||
use departure::{format_departures, get_departures_for_station, get_station_name_from_args};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let response = query_server()?;
|
||||
let station_name = get_station_name_from_args()?;
|
||||
let response = get_departures_for_station(station_name)?;
|
||||
let formatted = format_departures(response);
|
||||
println!("{formatted}");
|
||||
Ok(())
|
||||
|
||||
+42
-6
@@ -1,16 +1,52 @@
|
||||
use anyhow::Result;
|
||||
use ureq::Request;
|
||||
|
||||
use crate::response::Response;
|
||||
use crate::response::{PointFinderResponse, Response};
|
||||
|
||||
const DEPARTURE_MONITOR: &str = "https://webapi.vvo-online.de/dm";
|
||||
const POINT_FINDER: &str = "https://webapi.vvo-online.de/tr/pointfinder";
|
||||
|
||||
pub fn query_server() -> Result<Response> {
|
||||
let json_string = ureq::post(DEPARTURE_MONITOR)
|
||||
.set("Content-Type", "application/json")
|
||||
.set("charset", "UTF-8")
|
||||
.send_string("{\"stopid\":\"33006765\",\"limit\":5}")?
|
||||
pub fn get_departures_for_station(station_name: String) -> Result<Response> {
|
||||
let stopid = get_stopid_from_station_name(station_name)?;
|
||||
|
||||
let json_string = create_json_request(DEPARTURE_MONITOR)
|
||||
.send_string(&format!(
|
||||
"{{
|
||||
\"stopid\":\"{stopid}\",
|
||||
\"limit\":5
|
||||
}}"
|
||||
))?
|
||||
.into_string()?;
|
||||
|
||||
let result = serde_json::from_str(&json_string)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn get_stopid_from_station_name(station_name: String) -> Result<String> {
|
||||
let json_string = create_json_request(POINT_FINDER)
|
||||
.send_string(&format!(
|
||||
"{{
|
||||
\"query\":\"{station_name}\",
|
||||
\"limit\":1,
|
||||
\"regionalOnly\":\"true\",
|
||||
\"stopsOnly\":\"true\"
|
||||
}}"
|
||||
))?
|
||||
.into_string()?;
|
||||
|
||||
let response: PointFinderResponse = serde_json::from_str(&json_string)?;
|
||||
print!("{}", response.point.name);
|
||||
if let Some(area) = response.point.area {
|
||||
print!(", {area}");
|
||||
}
|
||||
println!("\n");
|
||||
|
||||
let result = response.point.stopid;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn create_json_request(url: &str) -> Request {
|
||||
ureq::post(url)
|
||||
.set("Content-Type", "application/json")
|
||||
.set("charset", "UTF-8")
|
||||
}
|
||||
|
||||
+49
-1
@@ -1,6 +1,6 @@
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::{Context, Result};
|
||||
use chrono::{DateTime, Local, TimeZone, Utc};
|
||||
use serde::{de, Deserialize, Deserializer};
|
||||
|
||||
@@ -72,3 +72,51 @@ pub fn format_departures(response: Response) -> String {
|
||||
let departures: Vec<String> = response.departures.iter().map(|d| d.to_string()).collect();
|
||||
departures.join("\n\n")
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct PointFinderResponse {
|
||||
#[serde(deserialize_with = "deserialize_points", rename = "Points")]
|
||||
pub point: Point,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct Point {
|
||||
pub stopid: String,
|
||||
pub name: String,
|
||||
pub area: Option<String>,
|
||||
}
|
||||
|
||||
impl From<(&str, &str, Option<&str>)> for Point {
|
||||
fn from(value: (&str, &str, Option<&str>)) -> Self {
|
||||
Self {
|
||||
stopid: value.0.into(),
|
||||
name: value.1.into(),
|
||||
area: value.2.map(|s| s.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Deserialize a Point Response in the form of
|
||||
/// '\"33000742|||Helmholtzstraße|5655904|4621157|0||\"'
|
||||
fn extract_data_from_response(line: &str) -> Result<Point> {
|
||||
let mut iter = line.trim_start_matches("\\\"").split_terminator('|');
|
||||
|
||||
let stopid = iter.next().context("getting stopid from line")?;
|
||||
let area = iter.nth(1).context("getting area from line").ok();
|
||||
let name = iter.next().context("getting stop name from line")?;
|
||||
Ok((stopid, name, area).into())
|
||||
}
|
||||
|
||||
fn deserialize_points<'de, D>(deserializer: D) -> Result<Point, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let stops: Vec<String> = Vec::deserialize(deserializer)?;
|
||||
let first_stop_line = stops
|
||||
.first()
|
||||
.ok_or_else(|| de::Error::custom("could not get first stop"))?;
|
||||
let point = extract_data_from_response(first_stop_line).map_err(de::Error::custom)?;
|
||||
Ok(point)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user