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;
|
mod query;
|
||||||
pub mod response;
|
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;
|
pub use response::format_departures;
|
||||||
|
|||||||
+3
-2
@@ -1,9 +1,10 @@
|
|||||||
use anyhow::Result;
|
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<()> {
|
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);
|
let formatted = format_departures(response);
|
||||||
println!("{formatted}");
|
println!("{formatted}");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
+42
-6
@@ -1,16 +1,52 @@
|
|||||||
use anyhow::Result;
|
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 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> {
|
pub fn get_departures_for_station(station_name: String) -> Result<Response> {
|
||||||
let json_string = ureq::post(DEPARTURE_MONITOR)
|
let stopid = get_stopid_from_station_name(station_name)?;
|
||||||
.set("Content-Type", "application/json")
|
|
||||||
.set("charset", "UTF-8")
|
let json_string = create_json_request(DEPARTURE_MONITOR)
|
||||||
.send_string("{\"stopid\":\"33006765\",\"limit\":5}")?
|
.send_string(&format!(
|
||||||
|
"{{
|
||||||
|
\"stopid\":\"{stopid}\",
|
||||||
|
\"limit\":5
|
||||||
|
}}"
|
||||||
|
))?
|
||||||
.into_string()?;
|
.into_string()?;
|
||||||
|
|
||||||
let result = serde_json::from_str(&json_string)?;
|
let result = serde_json::from_str(&json_string)?;
|
||||||
Ok(result)
|
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 std::fmt::{Debug, Display};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::{Context, Result};
|
||||||
use chrono::{DateTime, Local, TimeZone, Utc};
|
use chrono::{DateTime, Local, TimeZone, Utc};
|
||||||
use serde::{de, Deserialize, Deserializer};
|
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();
|
let departures: Vec<String> = response.departures.iter().map(|d| d.to_string()).collect();
|
||||||
departures.join("\n\n")
|
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