summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs433
1 files changed, 224 insertions, 209 deletions
diff --git a/src/main.rs b/src/main.rs
index 356db21..eacbeb9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,249 +7,264 @@ use traveltext::{iceportal::*, travelynx::*};
#[derive(Parser)]
struct Cli {
- #[clap(subcommand)]
- command: Command,
- /// print requests that couldn't be parsed to help debugging
- #[clap(long)]
- debug: bool,
- #[clap(default_value = "https://travelynx.de")]
- baseurl: String,
- /// API token to use in requests
- token: Option<String>,
+ #[clap(subcommand)]
+ command: Command,
+ /// print requests that couldn't be parsed to help debugging
+ #[clap(long)]
+ debug: bool,
+ #[clap(default_value = "https://travelynx.de")]
+ baseurl: String,
+ /// API token to use in requests
+ token: Option<String>
}
#[derive(Subcommand)]
enum Command {
- /// Get current travelynx status
- Status,
- /// Check in to a train using travelynx
- Checkin {
- from: String,
- to: String,
- // TODO: make this optional and guess which train if not given
- #[clap(flatten)]
- train: TrainRef,
- },
- /// (If already checked in) change the trip's destination
- Destination {
- to: String
- },
- Arewethereyet,
- /// If iceportal.de is available, ask it which train we're in and
- /// check in
- Autocheckin,
- /// Undo the last checkin (if any).
- Undo,
- /// Query iceportal.de (for testing)
- ICEPortal,
+ /// Get current travelynx status
+ Status,
+ /// Check in to a train using travelynx
+ Checkin {
+ from: String,
+ to: String,
+ // TODO: make this optional and guess which train if not given
+ #[clap(flatten)]
+ train: TrainRef
+ },
+ /// (If already checked in) change the trip's destination
+ Destination {
+ to: String
+ },
+ Arewethereyet,
+ /// If iceportal.de is available, ask it which train we're in and
+ /// check in
+ Autocheckin,
+ /// Undo the last checkin (if any).
+ Undo,
+ /// Query iceportal.de (for testing)
+ ICEPortal
}
#[derive(Deserialize)]
struct Config {
- token_status: String,
- token_travel: String,
+ token_status: String,
+ token_travel: String
}
fn main() -> Result<(), ureq::Error> {
- let cli = Cli::parse();
-
- let traveltext = format!(
- "{}{}el{}{}",
- "tr".cyan(),
- "av".bright_magenta(),
- "te".bright_magenta(),
- "xt".cyan()
- );
-
- let configpath = {
- let mut path = dirs::config_dir().unwrap();
- path.push("traveltext.toml");
- path
- };
-
- let config: Config = match std::fs::read_to_string(&configpath) {
- Ok(text) => match toml::from_str(&text) {
- Ok(config) => config,
- Err(err) => exit_err(
- &err.to_string(),
- &format!(
- "failed parsing config file {}",
- configpath.to_string_lossy()
- ),
+ let cli = Cli::parse();
+
+ let traveltext = format!(
+ "{}{}el{}{}",
+ "tr".cyan(),
+ "av".bright_magenta(),
+ "te".bright_magenta(),
+ "xt".cyan()
+ );
+
+ let configpath = {
+ let mut path = dirs::config_dir().unwrap();
+ path.push("traveltext.toml");
+ path
+ };
+
+ let config: Config = match std::fs::read_to_string(&configpath) {
+ Ok(text) => match toml::from_str(&text) {
+ Ok(config) => config,
+ Err(err) => exit_err(
+ &err.to_string(),
+ &format!(
+ "failed parsing config file {}",
+ configpath.to_string_lossy()
+ )
+ )
+ },
+ Err(err) => exit_err(
+ &err.to_string(),
+ &format!("failed reading config at: {}", configpath.to_string_lossy())
+ )
+ };
+
+ match cli.command {
+ Command::Status => {
+ let status: Status = exiting_get_request(
+ &format!("{}/api/v1/status/{}", cli.baseurl, config.token_status),
+ cli.debug
+ );
+
+ println!("{}: {}", traveltext, status);
+ }
+ Command::Arewethereyet => {
+ let status: Status = exiting_get_request(
+ &format!("{}/api/v1/status/{}", cli.baseurl, config.token_status),
+ cli.debug
+ );
+
+ match status.to_station {
+ None => println!("{}: Fahrt ins {}", traveltext, "Blaue".blue()),
+ Some(to) => {
+ let now = chrono::Utc::now();
+ let duration = to.real_arrival().map(|dt| *dt - now);
+ match duration {
+ Some(d) => println!(
+ "{}: we'll be there in {} minutes",
+ traveltext,
+ d.num_minutes()
),
- },
- Err(err) => exit_err(
- &err.to_string(),
- &format!("failed reading config at: {}", configpath.to_string_lossy()),
- ),
- };
-
- match cli.command {
- Command::Status => {
- let status: Status = exiting_get_request(
- &format!("{}/api/v1/status/{}", cli.baseurl, config.token_status),
- cli.debug,
- );
-
- println!("{}: {}", traveltext, status);
+ None => println!("{}: I have no idea", traveltext)
+ }
}
- Command::Arewethereyet => {
- let status: Status = exiting_get_request(
- &format!("{}/api/v1/status/{}", cli.baseurl, config.token_status),
- cli.debug,
- );
-
- match status.to_station {
- None => println!("{}: Fahrt ins {}", traveltext, "Blaue".blue()),
- Some(to) => {
- let now = chrono::Utc::now();
- let duration = to.real_arrival().map(|dt| *dt - now);
- match duration {
- Some (d) => println!(
- "{}: we'll be there in {} minutes",
- traveltext,
- d.num_minutes()
- ),
- None => println!("{}: I have no idea", traveltext)
- }
- }
- }
+ }
+ }
+ Command::Checkin { from, to, train } => {
+ let resp: Response = exiting_post_request(
+ &format!("{}/api/v1/travel", cli.baseurl),
+ Action::CheckIn {
+ train,
+ from_station: from,
+ to_station: Some(to),
+ comment: None,
+ token: format!("{}", config.token_travel)
},
- Command::Checkin { from, to, train } => {
- let resp: Response = exiting_post_request(
- &format!("{}/api/v1/travel", cli.baseurl),
- Action::CheckIn {
- train,
- from_station: from,
- to_station: Some(to),
- comment: None,
- token: format!("{}", config.token_travel),
- },
- cli.debug,
- );
-
- println!("{}: {}", traveltext, resp);
+ cli.debug
+ );
+
+ println!("{}: {}", traveltext, resp);
+ }
+ Command::Destination { to } => {
+ let resp: Response = exiting_post_request(
+ &format!("{}/api/v1/travel", cli.baseurl),
+ Action::CheckOut {
+ to_station: to,
+ force: false,
+ token: config.token_travel,
+ comment: None
},
- Command::Destination { to } => {
- let resp: Response = exiting_post_request(
- &format!("{}/api/v1/travel", cli.baseurl),
- Action::CheckOut {
- to_station: to,
- force: false,
- token: config.token_travel,
- comment: None
- },
- cli.debug
- );
- println!("{}: {}", traveltext, resp);
- }
- Command::Undo => {
- let resp: Response = exiting_post_request(
- &format!("{}/api/v1/travel", cli.baseurl),
- Action::Undo {
- token: config.token_travel.to_owned(),
- },
- cli.debug,
- );
-
- println!("{}: {}", traveltext, resp);
- }
- Command::Autocheckin => {
- let iceportal: TripInfo =
- exiting_get_request("https://iceportal.de/api1/rs/tripInfo/trip", cli.debug);
-
- let last_stop = iceportal.guess_last_station().unwrap();
- let train = iceportal.get_train_ref();
- println!(
- "{}: guessing you got onto {} {} in {}, checking in …",
- traveltext, train._type, train.no, last_stop
- );
- let resp: Response = exiting_post_request(
- &format!("{}/api/v1/travel", cli.baseurl),
- Action::CheckIn {
- train,
- from_station: last_stop,
- to_station: None,
- comment: None,
- token: format!("{}", config.token_travel),
- },
- cli.debug,
- );
-
- // eprintln!("{:?}", resp);
- println!("{}: {}", traveltext, resp);
+ cli.debug
+ );
+ println!("{}: {}", traveltext, resp);
+ }
+ Command::Undo => {
+ let resp: Response = exiting_post_request(
+ &format!("{}/api/v1/travel", cli.baseurl),
+ Action::Undo {
+ token: config.token_travel.to_owned()
+ },
+ cli.debug
+ );
+
+ println!("{}: {}", traveltext, resp);
+ }
+ Command::Autocheckin => {
+ let iceportal: TripInfo = exiting_get_request(
+ "https://iceportal.de/api1/rs/tripInfo/trip",
+ cli.debug
+ );
+
+ let last_stop = iceportal.guess_last_station().unwrap();
+ let train = iceportal.get_train_ref();
+ println!(
+ "{}: guessing you got onto {} {} in {}, checking in …",
+ traveltext, train._type, train.no, last_stop
+ );
+ let resp: Response = exiting_post_request(
+ &format!("{}/api/v1/travel", cli.baseurl),
+ Action::CheckIn {
+ train,
+ from_station: last_stop,
+ to_station: None,
+ comment: None,
+ token: format!("{}", config.token_travel)
+ },
+ cli.debug
+ );
+
+ // eprintln!("{:?}", resp);
+ println!("{}: {}", traveltext, resp);
+ }
+ Command::ICEPortal => {
+ match get_request::<TripInfo>(
+ "https://iceportal.de/api1/rs/tripInfo/trip"
+ ) {
+ Ok(resp) => {
+ println!(
+ "{}: Currently in {}\n",
+ traveltext,
+ resp.get_train_ref().to_string().green()
+ );
+ println!("guessing last stop was: {:?}\n", resp.guess_last_station());
+ println!("Stops:\n{}", resp.trip())
}
- Command::ICEPortal => {
- match get_request::<TripInfo>("https://iceportal.de/api1/rs/tripInfo/trip") {
- Ok(resp) => {
- println!("{}: Currently in {}\n", traveltext, resp.get_train_ref().to_string().green());
- println!("guessing last stop was: {:?}\n", resp.guess_last_station());
- println!("Stops:\n{}", resp.trip())
- }
- Err(err) => {
- if cli.debug {
- eprintln!("{:?}", err);
- }
- println!("either this tool or the iceportal broke or you're not actually on an ICE\n\
+ Err(err) => {
+ if cli.debug {
+ eprintln!("{:?}", err);
+ }
+ println!("either this tool or the iceportal broke or you're not actually on an ICE\n\
(get a response but couldn't parse it)");
- }
- }
}
+ }
}
- Ok(())
+ }
+ Ok(())
}
fn get_request<R>(uri: &str) -> Result<R, (serde_json::Error, String)>
where
- R: serde::de::DeserializeOwned,
+ R: serde::de::DeserializeOwned
{
- let resp: String = ureq::get(uri)
- .call()
- .unwrap_or_else(|err| exit_err(&err.to_string(), "get request failed"))
- .into_string()
- .unwrap_or_else(|err| exit_err(&err.to_string(), "get request response failed"));
-
- match serde_json::from_str::<R>(&resp) {
- Ok(obj) => Ok(obj),
- Err(err) => Err((err, resp)),
- }
+ let resp: String = ureq::get(uri)
+ .call()
+ .unwrap_or_else(|err| exit_err(&err.to_string(), "get request failed"))
+ .into_string()
+ .unwrap_or_else(|err| {
+ exit_err(&err.to_string(), "get request response failed")
+ });
+
+ match serde_json::from_str::<R>(&resp) {
+ Ok(obj) => Ok(obj),
+ Err(err) => Err((err, resp))
+ }
}
-fn exiting_get_request<R: serde::de::DeserializeOwned>(uri: &str, debug: bool) -> R {
- match get_request(uri) {
- Ok(obj) => obj,
- Err((err, resp)) => {
- if debug {
- eprintln!("DEBUG: {}", resp);
- }
- exit_err(&err.to_string(), "parsing response failed")
- }
+fn exiting_get_request<R: serde::de::DeserializeOwned>(
+ uri: &str,
+ debug: bool
+) -> R {
+ match get_request(uri) {
+ Ok(obj) => obj,
+ Err((err, resp)) => {
+ if debug {
+ eprintln!("DEBUG: {}", resp);
+ }
+ exit_err(&err.to_string(), "parsing response failed")
}
+ }
}
fn exiting_post_request<R, P>(uri: &str, payload: P, debug: bool) -> R
where
- P: serde::Serialize,
- R: serde::de::DeserializeOwned,
+ P: serde::Serialize,
+ R: serde::de::DeserializeOwned
{
- let resp: String = ureq::post(uri)
- .send_json(payload)
- .unwrap_or_else(|err| exit_err(&err.to_string(), "post request failed"))
- .into_string()
- .unwrap_or_else(|err| exit_err(&err.to_string(), "post request response failed"));
-
- match serde_json::from_str::<R>(&resp) {
- Ok(obj) => obj,
- Err(err) => {
- if debug {
- eprintln!("DEBUG: {}", resp);
- }
- exit_err(&err.to_string(), "parsing response failed")
- }
+ let resp: String = ureq::post(uri)
+ .send_json(payload)
+ .unwrap_or_else(|err| exit_err(&err.to_string(), "post request failed"))
+ .into_string()
+ .unwrap_or_else(|err| {
+ exit_err(&err.to_string(), "post request response failed")
+ });
+
+ match serde_json::from_str::<R>(&resp) {
+ Ok(obj) => obj,
+ Err(err) => {
+ if debug {
+ eprintln!("DEBUG: {}", resp);
+ }
+ exit_err(&err.to_string(), "parsing response failed")
}
+ }
}
fn exit_err(msg: &str, scope: &str) -> ! {
- eprintln!("{}: {}", scope, msg);
- std::process::exit(1)
+ eprintln!("{}: {}", scope, msg);
+ std::process::exit(1)
}