summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorstuebinm2022-04-21 22:07:49 +0200
committerstuebinm2022-04-21 22:10:22 +0200
commit46b32e7df4d9ff89674217944b1f301c46e20e3a (patch)
tree755193f36a63a87f76645f31f7b4f7a6d19a3e3e /src
parent0de9008a3df42d171f01f0d431861c9d765b5234 (diff)
add import from hafas to travelynx
(using yuka's hafas-rs)
Diffstat (limited to 'src')
-rw-r--r--src/main.rs144
1 files changed, 134 insertions, 10 deletions
diff --git a/src/main.rs b/src/main.rs
index f41d871..2f3a34e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,10 +1,18 @@
+use chrono::{DateTime, Utc};
use clap::{Parser, Subcommand};
use colored::*;
use serde::Deserialize;
+use serde_json::json;
use traveltext::onboard::{choose_api, OnBoardAPI};
use traveltext::{traits::*, travelynx::*, types::*};
+use hafas_rs::api::journeys::*;
+use hafas_rs::api::locations::*;
+use hafas_rs::client::HafasClient;
+use hafas_rs::profile::db::DbProfile;
+use hafas_rs::requester::hyper::HyperRustlsRequester;
+use hafas_rs::{Place, ProductsSelection};
#[derive(Parser)]
struct Cli {
@@ -15,8 +23,6 @@ struct Cli {
debug: bool,
#[clap(default_value = "https://travelynx.de")]
baseurl: String,
- /// API token to use in requests
- token: Option<String>
}
#[derive(Subcommand)]
@@ -40,8 +46,21 @@ enum Command {
From {
from: String
},
- Station {
- station: String
+ /// Find a (single) trip of a single train via HAFAS.
+ /// Mostly intended to ferry trip-data into travelynx 'by hand' if it doesn't know some connection
+ Journey {
+ /// starting station's name (fuzzy-matched)
+ from_name: String,
+ /// destination station's name (fuzzy-matched)
+ to_name: String,
+ /// departure time; takes the next available connection
+ time: Option<DateTime<Utc>>,
+ /// set the dryRun flag to 'true' when importing to travelynx
+ #[clap(short = 'd', long = "dry-run")]
+ dry_run: bool,
+ /// import the found trip into travelynx (needs the token_import config option!)
+ #[clap(short = 'i', long = "import")]
+ import: bool
},
Arewethereyet,
/// If iceportal.de is available, ask it which train we're in and
@@ -60,10 +79,12 @@ enum Command {
#[derive(Deserialize)]
struct Config {
token_status: String,
- token_travel: String
+ token_travel: String,
+ token_import: Option<String>
}
-fn main() -> Result<(), ureq::Error> {
+#[tokio::main]
+async fn main() -> Result<(), ureq::Error> {
let cli = Cli::parse();
let traveltext = format!(
@@ -152,7 +173,11 @@ fn main() -> Result<(), ureq::Error> {
println!("{}: {}", traveltext, resp);
}
Command::From { from } => {
- println!("{}: {}", traveltext, "warning: this command may pollute your trip history".red());
+ println!(
+ "{}: {}",
+ traveltext,
+ "warning: this command may pollute your trip history".red()
+ );
let status: Status = exiting_get_request(
&format!("{}/api/v1/status/{}", cli.baseurl, config.token_status),
cli.debug
@@ -251,9 +276,108 @@ fn main() -> Result<(), ureq::Error> {
}
}
}
- Command::Station { station } => {
- // let c = HafasClient::new(DbProfile, HyperRustlsRequester::new());
- // println!("{:#?}", c.suggestions("München Hbf", None).await.unwrap());
+ Command::Journey {
+ from_name,
+ to_name,
+ time,
+ dry_run,
+ import
+ } => {
+ let c = HafasClient::new(DbProfile, HyperRustlsRequester::new());
+ let from = &c
+ .locations(LocationsOptions {
+ query: from_name,
+ results: None,
+ // TODO: respect locale set
+ language: Some("de".to_string())
+ })
+ .await
+ .unwrap()[0];
+
+ let to = &c
+ .locations(LocationsOptions {
+ query: to_name,
+ results: None,
+ language: None
+ })
+ .await
+ .unwrap()[0];
+
+ let opts = JourneysOptions {
+ products: ProductsSelection {
+ bus: Some(false),
+ ..ProductsSelection::default()
+ },
+ departure: time.map(|t| t.timestamp()), //Some(1650536340);
+ stopovers: Some(true),
+ language: Some("de".to_string()),
+ ..JourneysOptions::default()
+ };
+
+ let journey = &c
+ .journeys(from.clone(), to.clone(), opts)
+ .await
+ .unwrap()
+ .journeys[0]
+ .legs[0];
+
+ let stops = journey.stopovers.as_ref().unwrap();
+
+ println!("{}: found this trip:", traveltext);
+
+ for stop in stops {
+ match &stop.stop {
+ Place::Stop(station) => {
+ println!("{}", station.name.as_ref().unwrap())
+ }
+ _ => panic!("this train stops somewhere that's not a station??")
+ }
+ stop.arrival.map(|t| println!("arr: {:?}", t.to_rfc3339()));
+ stop.departure.map(|t| println!("dep: {:?}", t.to_rfc3339()));
+ }
+
+ if import {
+ let travelynx = json!({
+ "token": config.token_import.unwrap(),
+ "dryRun": dry_run,
+ "fromStation": match &stops[0].stop {
+ Place::Stop (station) => json!({
+ "name":station.name,
+ "scheduledTime":stops[0].departure.unwrap().timestamp()
+ }),
+ _ => panic!("this trip lacks a first station?")
+ },
+ "toStation": match &stops[stops.len()-1].stop {
+ Place::Stop (station) => json!({
+ "name": station.name,
+ "scheduledTime": stops[stops.len()-1].arrival.unwrap().timestamp()
+ }),
+ _ => panic!("this trip lacks an end station?")
+ },
+ "train": match &journey.line {
+ Some(line) => json!({
+ "type": line.name.as_ref().unwrap().split_ascii_whitespace().next().unwrap(),
+ "line": serde_json::Value::Null,
+ "no": line.fahrt_nr.as_ref().unwrap()
+ }),
+ None => panic!("could not find train information")
+ },
+ "intermediateStops": &stops[1..stops.len()-1]
+ .iter()
+ .filter_map(|s| match &s.stop {
+ Place::Stop (station) => station.name.as_ref(),
+ _ => None
+ })
+ .collect::<Vec<&String>>()
+ });
+ let resp: serde_json::Value = exiting_post_request(
+ &format!("{}/api/v1/import", cli.baseurl),
+ travelynx,
+ cli.debug
+ );
+
+ println!("{:?}", resp);
+ }
}
}
Ok(())