Provide colorful user interface and error handling
This commit is contained in:
parent
a29322f108
commit
eb79a65500
|
@ -1,3 +1,4 @@
|
|||
use core::fmt;
|
||||
use std::{path::{PathBuf, Path}, io};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -92,3 +93,81 @@ impl AviaryError {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for AviaryError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "\x1b[31mError!\x1b[0m\n")?;
|
||||
match self {
|
||||
Self::FileDNE(path) =>
|
||||
writeln!(f, "The file at \x1b[36m{}\x1b[0m does not exist", path.display()),
|
||||
|
||||
Self::ReadPermissionDenied(path) =>
|
||||
writeln!(f, "Permission denied for the file \x1b[36m{}\x1b[0m", path.display()),
|
||||
|
||||
Self::StreamReadError(path, err) =>
|
||||
writeln!(f,
|
||||
concat!(
|
||||
"Something bad happened while we were reading from ",
|
||||
"\x1b[36m{}\x1b[0m. This could be caused by removing a ",
|
||||
"drive/phone without unplugging it, or several other possible ",
|
||||
"things. This error might give you a clue:\n\n{}"
|
||||
),
|
||||
path.display(), err
|
||||
),
|
||||
|
||||
Self::ImageFormatError(path) =>
|
||||
writeln!(f,
|
||||
concat!(
|
||||
"We had a little bit of trouble understanding the image at ",
|
||||
"\x1b[36m{}\x1b[0m. Normally, this indicates that it might not be ",
|
||||
"an image file (e.g. if it's a video instead). If you're sure that ",
|
||||
"it's an image, this could indicate that it's corrupted or of an ",
|
||||
"unsupported format.\n\n",
|
||||
"\x1b[34mSupported formats:\x1b[0m\n",
|
||||
" - gif\n",
|
||||
" - jpg\n",
|
||||
" - ico\n",
|
||||
" - png\n",
|
||||
" - tiff\n",
|
||||
" - webp\n",
|
||||
" - bmp\n",
|
||||
" - hdr",
|
||||
),
|
||||
path.display(),
|
||||
),
|
||||
|
||||
Self::ServerError(msg) =>
|
||||
writeln!(f,
|
||||
concat!(
|
||||
"The server seems to be down or misbehaving at the minute. ",
|
||||
"Normally, this issue should resolve by itself once the server ",
|
||||
"maintainers identify the problem and fix it.\n\n",
|
||||
"If the issue persists, please submit an issue on the bug ",
|
||||
"tracker. This error message may help to identify the problem:",
|
||||
"\n\n\x1b[31m{}\x1b[0m",
|
||||
),
|
||||
msg,
|
||||
),
|
||||
|
||||
Self::ConnectionError(msg) =>
|
||||
writeln!(f,
|
||||
concat!(
|
||||
"There was an issue connecting to the server! Check that your ",
|
||||
"internet is online, and you can access websites normally. ",
|
||||
"This information might help diagnose the issue:\n\n",
|
||||
"\x1b[31m{}\x1b[0m",
|
||||
),
|
||||
msg,
|
||||
),
|
||||
|
||||
Self::BadServerParameter =>
|
||||
writeln!(f,
|
||||
concat!(
|
||||
"The server URL you provided was \x1b[31minvalid\x1b[0m! ",
|
||||
"Please check to make sure that it is properly formatted, like ",
|
||||
"\x1b[1m0x0.st\x1b[0m or \x1b[1menvs.sh\x1b[0m.",
|
||||
),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
28
src/main.rs
28
src/main.rs
|
@ -33,6 +33,7 @@ fn trim_url<'a>(base_url: &str, url: &'a str) -> Option<&'a str> {
|
|||
|
||||
fn main() {
|
||||
let args: parse::Args = argh::from_env();
|
||||
print!("Checking files...");
|
||||
let (files, errors): (Vec<_>, Vec<_>) = args.images.iter()
|
||||
.map(Path::new)
|
||||
.map(|path| File::open(path)
|
||||
|
@ -42,7 +43,7 @@ fn main() {
|
|||
.partition_result();
|
||||
|
||||
if !errors.is_empty() {
|
||||
println!("[FATAL] The was a problem accessing some of the files you provided!");
|
||||
println!(" \x1b[31mError!\x1b[0m");
|
||||
let (nonexistant, noread): (Vec<_>, Vec<_>) = errors.iter()
|
||||
.partition_map(|e| match e {
|
||||
AviaryError::FileDNE(path) => Either::Left(path),
|
||||
|
@ -51,13 +52,14 @@ fn main() {
|
|||
});
|
||||
if !nonexistant.is_empty() {
|
||||
println!("\nWe didn't see any files at the following locations:");
|
||||
nonexistant.iter().for_each(|path| println!("{}", path.display()));
|
||||
nonexistant.iter().for_each(|path| println!("\x1b[37m- \x1b[31m{}", path.display()));
|
||||
}
|
||||
if !noread.is_empty() {
|
||||
println!("\nWe found these files, but didn't have permission to open them:");
|
||||
noread.iter().for_each(|path| println!("{}", path.display()));
|
||||
println!("\x1b[0m\nWe found these files, but didn't have permission to open them:");
|
||||
noread.iter().for_each(|path| println!("\x1b[37m- \x1b[31m{}", path.display()));
|
||||
}
|
||||
} else {
|
||||
println!(" \x1b[32mDone!\n");
|
||||
let agent = upload::get_agent();
|
||||
let full_server = if args.server.starts_with("http") {
|
||||
Cow::Borrowed(&args.server)
|
||||
|
@ -65,6 +67,7 @@ fn main() {
|
|||
Cow::Owned(format!("https://{}", args.server))
|
||||
};
|
||||
let index_url = files.into_iter()
|
||||
.inspect(|(path, _)| print!("\x1b[36m{}\x1b[0m\n\x1b[37m├─\x1b[0m Reading... ", path.display()))
|
||||
.map(|(path, mut file)|
|
||||
(|| {
|
||||
let mut buff = Vec::with_capacity(file.metadata()?.len() as usize);
|
||||
|
@ -72,11 +75,13 @@ fn main() {
|
|||
Ok((path, buff))
|
||||
})().map_err(|e| AviaryError::StreamReadError(path.to_owned(), e))
|
||||
)
|
||||
.inspect(|r| if r.is_ok() { print!("\x1b[32mDone!\n\x1b[37m├─\x1b[0m Thumbnailing... ") })
|
||||
.map(|r| r.and_then(|(path, raw_dat)| {
|
||||
let (thumbnail, blurhash) = thumbnailing::thumbnail(&raw_dat)
|
||||
.map_err(|_| AviaryError::ImageFormatError(path.to_owned()))?;
|
||||
Ok((raw_dat, thumbnail, blurhash))
|
||||
}))
|
||||
.inspect(|r| if r.is_ok() { print!("\x1b[32mDone!\n\x1b[37m├─\x1b[0m Encrypting... ")})
|
||||
.map_ok(|(raw_dat, thumbnail, blurhash)| {
|
||||
let key = crypto::make_key();
|
||||
(
|
||||
|
@ -86,6 +91,7 @@ fn main() {
|
|||
blurhash
|
||||
)
|
||||
})
|
||||
.inspect(|r| if r.is_ok() { print!("\x1b[32mDone!\n\x1b[37m└─\x1b[0m Uploading... ")})
|
||||
.map(|r| r.and_then(|(key, full_img, thumb, blurhash)|
|
||||
upload::put_data(&agent, &*full_server, &thumb)
|
||||
.and_then(|thumb_url|
|
||||
|
@ -102,6 +108,7 @@ fn main() {
|
|||
Err(AviaryError::ServerError(format!("Received bad response from server: {}", full_url)))
|
||||
}
|
||||
}))
|
||||
.inspect(|r| if r.is_ok() { println!("\x1b[32mDone!\n")})
|
||||
.map_ok(|(key, full_url, thumb_url, blurhash)| protobuf::image::Image {
|
||||
key: key.into(),
|
||||
full_url, thumb_url, blurhash,
|
||||
|
@ -122,11 +129,16 @@ fn main() {
|
|||
.expect("Error serializing protocol buffers")
|
||||
);
|
||||
let encoded_key = base64::encode(index_key);
|
||||
print!("\x1b[0mUploading index... ");
|
||||
upload::put_data(&agent, &*full_server, &encrypted_index)
|
||||
.map_err(|e| AviaryError::from_upload_error(e))
|
||||
.map(|url| format!("{}#{}", url.trim(), &encoded_key))
|
||||
})
|
||||
.unwrap();
|
||||
println!("Success! {}", index_url);
|
||||
.map(|url| format!("{}#{}", url.trim().trim_end_matches(".bin"), &encoded_key))
|
||||
});
|
||||
match index_url {
|
||||
Ok(url) =>
|
||||
println!("\x1b[32mDone!\n\n\x1b[34mYour gallery is: \x1b[1;0m{}", url),
|
||||
Err(e) =>
|
||||
print!("{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue