2025-06-02 23:57:17 +00:00
|
|
|
|
mod appstate;
|
2025-05-28 00:07:59 +00:00
|
|
|
|
mod cli;
|
2025-06-10 18:20:52 +00:00
|
|
|
|
mod file;
|
2025-05-22 17:34:44 +00:00
|
|
|
|
mod sharry;
|
|
|
|
|
|
|
2025-06-05 01:44:39 +00:00
|
|
|
|
use std::{
|
|
|
|
|
|
process::exit,
|
|
|
|
|
|
sync::{
|
|
|
|
|
|
Arc,
|
|
|
|
|
|
atomic::{AtomicBool, Ordering},
|
|
|
|
|
|
},
|
2025-06-05 01:34:12 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-05-27 14:01:09 +00:00
|
|
|
|
use clap::Parser;
|
2025-06-05 12:09:47 +00:00
|
|
|
|
use console::style;
|
2025-06-05 11:20:27 +00:00
|
|
|
|
use dialoguer::{Confirm, theme::ColorfulTheme};
|
2025-06-05 01:13:54 +00:00
|
|
|
|
use log::{error, info};
|
2025-05-22 17:34:44 +00:00
|
|
|
|
use ureq::Agent;
|
|
|
|
|
|
|
2025-06-02 23:57:17 +00:00
|
|
|
|
use appstate::AppState;
|
2025-05-28 00:07:59 +00:00
|
|
|
|
use cli::Cli;
|
2025-06-08 21:31:50 +00:00
|
|
|
|
use sharry::ClientError;
|
2025-05-27 14:01:09 +00:00
|
|
|
|
|
2025-05-17 23:57:52 +00:00
|
|
|
|
fn main() {
|
2025-06-05 17:37:35 +00:00
|
|
|
|
println!(
|
|
|
|
|
|
"{} to {}!",
|
|
|
|
|
|
style("Welcome").magenta().bold(),
|
|
|
|
|
|
style("ShrUpl").yellow().bold(),
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2025-06-05 10:01:09 +00:00
|
|
|
|
let stop = Arc::new(AtomicBool::new(false));
|
2025-06-05 01:34:12 +00:00
|
|
|
|
|
2025-06-05 10:01:09 +00:00
|
|
|
|
let stop_ctrlc = stop.clone();
|
|
|
|
|
|
ctrlc::set_handler(move || {
|
|
|
|
|
|
stop_ctrlc.store(true, Ordering::SeqCst);
|
2025-06-05 12:58:09 +00:00
|
|
|
|
info!("stopping as soon as possible ...");
|
2025-06-05 10:01:09 +00:00
|
|
|
|
})
|
|
|
|
|
|
.expect("Error setting Ctrl-C handler");
|
2025-06-05 01:34:12 +00:00
|
|
|
|
|
2025-05-22 17:34:44 +00:00
|
|
|
|
env_logger::init();
|
|
|
|
|
|
|
2025-05-28 00:07:59 +00:00
|
|
|
|
let args = Cli::parse();
|
|
|
|
|
|
info!("args: {args:?}");
|
2025-05-28 13:42:31 +00:00
|
|
|
|
info!("timeout: {:?}", args.get_timeout());
|
2025-05-28 00:07:59 +00:00
|
|
|
|
|
2025-05-22 17:34:44 +00:00
|
|
|
|
let agent: Agent = Agent::config_builder()
|
2025-05-28 13:42:31 +00:00
|
|
|
|
.timeout_global(args.get_timeout())
|
2025-05-22 17:34:44 +00:00
|
|
|
|
.build()
|
|
|
|
|
|
.into();
|
|
|
|
|
|
|
2025-06-05 11:20:27 +00:00
|
|
|
|
let mut state = AppState::try_resume(&args)
|
|
|
|
|
|
.and_then(|state| {
|
|
|
|
|
|
Confirm::with_theme(&ColorfulTheme::default())
|
2025-06-05 17:37:35 +00:00
|
|
|
|
.with_prompt("Continue previously stopped operation?")
|
2025-06-05 11:20:27 +00:00
|
|
|
|
.default(true)
|
|
|
|
|
|
.interact()
|
|
|
|
|
|
.map_or(None, |b| b.then_some(state))
|
|
|
|
|
|
})
|
2025-06-05 12:58:09 +00:00
|
|
|
|
.unwrap_or_else(|| {
|
|
|
|
|
|
stop.load(Ordering::SeqCst).then(|| exit(0));
|
|
|
|
|
|
|
|
|
|
|
|
match AppState::from_args(&args, &agent) {
|
|
|
|
|
|
Ok(state) => {
|
2025-06-05 22:08:24 +00:00
|
|
|
|
state.save().unwrap(); // HACK unwrap
|
2025-06-05 12:58:09 +00:00
|
|
|
|
state
|
2025-06-05 12:09:47 +00:00
|
|
|
|
}
|
2025-06-05 12:58:09 +00:00
|
|
|
|
Err(e) => {
|
|
|
|
|
|
if let Some(cause) = match e {
|
2025-06-08 21:31:50 +00:00
|
|
|
|
ClientError::ResponseStatus {
|
|
|
|
|
|
actual: _,
|
|
|
|
|
|
expected: 403,
|
|
|
|
|
|
} => Some("Alias ID"),
|
2025-06-10 18:20:52 +00:00
|
|
|
|
// ClientError::FileIO(_) => Some("URL"),
|
2025-06-05 12:58:09 +00:00
|
|
|
|
_ => None,
|
|
|
|
|
|
} {
|
2025-06-05 17:37:35 +00:00
|
|
|
|
info!("handling error: {e:?}");
|
2025-06-05 12:58:09 +00:00
|
|
|
|
println!(
|
|
|
|
|
|
"{} probably wrong: {} – {:?}",
|
2025-06-05 17:37:35 +00:00
|
|
|
|
style("Error!").red().bold(),
|
|
|
|
|
|
style(cause).cyan().italic(),
|
2025-06-05 12:58:09 +00:00
|
|
|
|
style(e.to_string()).yellow()
|
|
|
|
|
|
);
|
|
|
|
|
|
} else {
|
2025-06-05 17:37:35 +00:00
|
|
|
|
error!("unknown error: {e} – {e:?}");
|
|
|
|
|
|
println!("{}", style("Unknown Error!").red().bold());
|
2025-06-05 12:58:09 +00:00
|
|
|
|
}
|
2025-06-05 12:09:47 +00:00
|
|
|
|
|
2025-06-05 12:58:09 +00:00
|
|
|
|
exit(1);
|
|
|
|
|
|
}
|
2025-06-05 11:20:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-06-04 21:02:35 +00:00
|
|
|
|
|
2025-06-05 17:37:35 +00:00
|
|
|
|
println!(
|
|
|
|
|
|
"{} uploading: {}",
|
|
|
|
|
|
style("ShrUpl").yellow().bold(),
|
|
|
|
|
|
style(state.file_names().join(", ")).magenta(),
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2025-06-04 21:02:35 +00:00
|
|
|
|
info!("continuing with state: {state:?}");
|
|
|
|
|
|
|
2025-06-05 01:13:54 +00:00
|
|
|
|
loop {
|
2025-06-10 23:39:08 +00:00
|
|
|
|
match state.upload_chunk(&agent) {
|
2025-06-05 01:13:54 +00:00
|
|
|
|
Err(e) => error!("error: {e:?}"),
|
2025-06-05 11:20:27 +00:00
|
|
|
|
Ok(None) => {
|
|
|
|
|
|
info!("all uploads done");
|
2025-06-05 22:08:24 +00:00
|
|
|
|
state.clear().unwrap(); // HACK unwrap
|
2025-06-05 11:20:27 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-06-05 01:13:54 +00:00
|
|
|
|
_ => (),
|
2025-06-04 16:44:16 +00:00
|
|
|
|
}
|
2025-06-05 01:13:54 +00:00
|
|
|
|
|
2025-06-05 22:08:24 +00:00
|
|
|
|
state.save().unwrap(); // HACK unwrap
|
2025-06-05 10:01:09 +00:00
|
|
|
|
stop.load(Ordering::SeqCst).then(|| exit(0));
|
2025-05-26 20:31:22 +00:00
|
|
|
|
}
|
2025-05-17 23:57:52 +00:00
|
|
|
|
}
|