Added a pretty UI for happy path downloads

This commit is contained in:
Emi Simpson 2022-08-17 15:39:07 -04:00
parent e97bc5a42e
commit 9a02ab991e
Signed by: Emi
GPG key ID: A12F2C2FFDC3D847
2 changed files with 39 additions and 21 deletions

View file

@ -188,19 +188,27 @@ fn download(server: &str, args: DownloadArgs) -> Result<(), AviaryDownloadError>
.try_into()
.map_err(|_| AviaryDownloadError::MalformedKey(false))?;
let download_agent = upload::get_agent();
print!("Downloading index... ");
let encrypted_index = upload::get_data(&download_agent, &index_url, 500_000, &mut download_buffer)
.map_err(AviaryDownloadError::from_download_error(true))?;
let serialized_index = crypto::decrypt(&key, &encrypted_index, &mut decrypt_buffer)
.ok_or(AviaryDownloadError::KeyMismatch)?;
let index = protobuf::index::Index::parse_from_bytes(&serialized_index)
.map_err(|_| AviaryDownloadError::CorruptIndex("Index was not a valid protobuf structure"))?;
println!("{index:?}");
let image_count = index.images.len();
println!(
"\x1b[32mDone!\x1b[0m\n\nGallery Name: {}\n Image Count: {}\n\n(desc not implemented)\n",
index.title.as_ref().map(String::as_str).unwrap_or("<not set>"),
image_count
);
let dest_dir: Cow<Path> = args.output.map(Cow::Owned)
.unwrap_or_else(||
index.title.map(|title|
Cow::Owned(sanitise_with_options(&title, &SANITIZATION_OPTIONS).into()))
.unwrap_or(Cow::Borrowed("Unnamed-Album".as_ref())));
fs::create_dir_all(&dest_dir).map_err(|e| match e.kind() {
io::ErrorKind::PermissionDenied =>
AviaryDownloadError::PermissionDenied(dest_dir.as_ref().to_owned()),
@ -208,23 +216,6 @@ fn download(server: &str, args: DownloadArgs) -> Result<(), AviaryDownloadError>
})?;
for (indx, image) in index.images.into_iter().enumerate() {
// Print a little blurhash
const BH_WIDTH: u32 = 12;
const BH_HEIGHT: u32 = 5;
let blur = blurhash::decode(&image.blurhash, BH_WIDTH, BH_HEIGHT, 1.0);
let mut blur = blur.iter();
for _ in 0..BH_HEIGHT {
for _ in 0..BH_WIDTH {
let r = blur.next().unwrap();
let g = blur.next().unwrap();
let b = blur.next().unwrap();
let _ = blur.next().unwrap();
print!("\x1b[38;2;{r};{g};{b}m█");
}
print!("\n");
}
print!("\x1b[0m");
let extension = image.format.enum_value().map(|f| match f {
Format::PNG => "png",
Format::WEBP => "webp",
@ -232,6 +223,28 @@ fn download(server: &str, args: DownloadArgs) -> Result<(), AviaryDownloadError>
Format::JPG => "jpg",
Format::GIF => "gif",
}).unwrap_or("unk");
// Print a little blurhash
const BH_WIDTH: u32 = 12;
const BH_HEIGHT: u32 = 5;
let blur = blurhash::decode(&image.blurhash, BH_WIDTH, BH_HEIGHT, 1.0);
let mut blur = blur.iter();
for y in 0..BH_HEIGHT {
for _ in 0..BH_WIDTH {
let r = blur.next().unwrap();
let g = blur.next().unwrap();
let b = blur.next().unwrap();
let _ = blur.next().unwrap();
print!("\x1b[38;2;{r};{g};{b}m█");
}
match y {
1 => println!("\x1b[0m Image {}/{}", indx + 1, image_count),
2 => println!("\x1b[0m Format: {}", extension),
_ => println!(""),
}
}
print!("\x1b[37m├─\x1b[0m Reserving file... ");
stdout().flush().unwrap();
let path = dest_dir.join(format!("{indx:03}.{extension}"));
let mut dest_file = OpenOptions::new()
.write(true)
@ -251,17 +264,23 @@ fn download(server: &str, args: DownloadArgs) -> Result<(), AviaryDownloadError>
.map_err(|_|
AviaryDownloadError::CorruptIndex("Key of invalid length specified in index")
)?;
print!("\x1b[32mDone!\n\x1b[37m├─\x1b[0m Dowloading... ");
stdout().flush().unwrap();
let encrypted_thumbnail = upload::get_data(
&download_agent,
&format!("{}/{}.bin", server, image.full_url),
7680_000,
&mut download_buffer
).map_err(AviaryDownloadError::from_download_error(false))?;
print!("\x1b[32mDone!\n\x1b[37m├─\x1b[0m Decrypting... ");
stdout().flush().unwrap();
let decrypted_thumb = crypto::decrypt(
&key,
encrypted_thumbnail,
&mut decrypt_buffer
).ok_or(AviaryDownloadError::ExpiredImage)?;
print!("\x1b[32mDone!\n\x1b[37m└─\x1b[0m Saving... ");
stdout().flush().unwrap();
dest_file.write_all(&decrypted_thumb)
.map_err(|e| match e.kind() {
io::ErrorKind::PermissionDenied =>
@ -270,6 +289,7 @@ fn download(server: &str, args: DownloadArgs) -> Result<(), AviaryDownloadError>
AviaryDownloadError::Cancelled,
_ => AviaryDownloadError::FilesystemError(e, path.clone())
})?;
println!("\x1b[32mDone!\n");
}
Ok(())

View file

@ -21,12 +21,10 @@ pub fn put_data(agent: &Agent, server: &str, data: &[u8]) -> Result<String, ureq
pub fn get_data<'b>(agent: &Agent, location: &str, size_limit: u64, buffer: &'b mut Vec<u8>) -> Result<&'b mut Vec<u8>, ureq::Error> {
buffer.clear();
println!("{}", location);
let read = agent.get(location)
agent.get(location)
.call()?
.into_reader()
.take(size_limit)
.read_to_end(buffer)?;
println!("{}", read);
Ok(buffer)
}