115 lines
3.2 KiB
Rust
115 lines
3.2 KiB
Rust
mod api;
|
|
mod cmd;
|
|
mod config;
|
|
mod errors;
|
|
|
|
use api::API;
|
|
use chrono::NaiveDateTime;
|
|
use cmd::*;
|
|
use config::Config;
|
|
use errors::GenericError;
|
|
use std::fs::File;
|
|
use std::io::prelude::*;
|
|
use std::sync::mpsc::TryRecvError;
|
|
|
|
fn main() {
|
|
let env: EnvOpt = argh::from_env();
|
|
if let Err(e) = from_env(env) {
|
|
eprintln!("Error: {:?}", e);
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
|
|
fn from_env(env: EnvOpt) -> Result<(), GenericError> {
|
|
match env.subcommand {
|
|
Subcommand::Run(opt) => {
|
|
let mut file = File::open("config.toml")?;
|
|
let mut string = String::new();
|
|
file.read_to_string(&mut string)?;
|
|
|
|
let config: Config = toml::from_str(&string)?;
|
|
|
|
run(
|
|
&config,
|
|
Some("1.1.2015 00:00:00".to_owned()),
|
|
Some("1.5.2021 00:00:00".to_owned()),
|
|
)?;
|
|
Ok(())
|
|
}
|
|
Subcommand::Init(opt) => {
|
|
let config = Config::default();
|
|
|
|
let mut file = File::create("config.toml").unwrap();
|
|
file.write_all(&toml::to_vec(&config).unwrap())?;
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
fn run(config: &Config, from: Option<String>, to: Option<String>) -> Result<(), GenericError> {
|
|
let mut api = API::new(config.clone());
|
|
|
|
let from = get_opt(from.map(|f| NaiveDateTime::parse_from_str(&f, &config.between_format)))?;
|
|
let to = get_opt(to.map(|t| NaiveDateTime::parse_from_str(&t, &config.between_format)))?;
|
|
|
|
let tags = api.get_tags()?;
|
|
let first_tag = tags[0].id.clone().unwrap();
|
|
let state_list = api.get_states(&first_tag)?;
|
|
|
|
let states = API::get_between(&state_list, from, to, true, &config);
|
|
|
|
let mut locations = Vec::new();
|
|
for (_, state) in states.iter() {
|
|
api.queue_location(&first_tag, state.id.as_ref().unwrap());
|
|
}
|
|
let receiver = api.begin_location_fetch();
|
|
let mut counter = 0;
|
|
loop {
|
|
match receiver.try_recv() {
|
|
Ok(res) => match res {
|
|
Ok(loc) => {
|
|
counter += 1;
|
|
println!(
|
|
"Currently: {:#.2}%",
|
|
counter as f32 / states.len() as f32 * 100.
|
|
);
|
|
match loc {
|
|
Ok(mut loc) => locations.append(&mut loc),
|
|
Err(e) => println!("Error: {}", e.message.unwrap_or(String::new())),
|
|
}
|
|
}
|
|
Err(e) => eprintln!("{:?}", e),
|
|
},
|
|
Err(e) => {
|
|
if let TryRecvError::Disconnected = e {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
locations.sort_by(|loc1, loc2| loc2.timestamp.cmp(&loc1.timestamp));
|
|
|
|
let locs = API::get_between(&locations, from, to, false, &config);
|
|
dbg!(
|
|
&locs.iter().map(|loc| loc.0).collect::<Vec<NaiveDateTime>>(),
|
|
locs.len(),
|
|
locations.len()
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
fn get_opt<A, B>(option: Option<Result<A, B>>) -> Result<Option<A>, B> {
|
|
if let Some(res) = option {
|
|
match res {
|
|
Ok(a) => Ok(Some(a)),
|
|
Err(b) => Err(b),
|
|
}
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
fn exp_time(api: &API, reqs_left: u32) -> f32 {
|
|
(reqs_left * api.last_response_ping) as f32 / 1000.
|
|
}
|