diff --git a/src/main.rs b/src/main.rs index 061b53a..efb21b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ mod errors; use std::{borrow::Cow, io::stdout}; use std::io::{Read, Write}; -use std::fs::File; +use std::fs::{File, self, OpenOptions}; use std::path::Path; use errors::AviaryError; @@ -171,5 +171,33 @@ fn download(server: &str, args: DownloadArgs) { .expect("wrong key or corrupt index"); let index = protobuf::index::Index::parse_from_bytes(&serialized_index) .expect("malformed index"); - println!("{index:?}"); + + let dest_dir: Cow = args.output.map(Cow::Owned) + .unwrap_or_else(|| Cow::Borrowed( + index.title.as_ref() + .map(String::as_str) + .unwrap_or("Unnamed-Album").as_ref())); + fs::create_dir_all(&dest_dir).expect("Failed to create destination directory"); + for (indx, image) in index.images.into_iter().enumerate() { + let path = dest_dir.join(format!("{indx:03}.webp")); + let mut dest_file = OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(path) + .expect("Failed to open"); + let key = image.key.try_into().expect("Invalid key size"); + let encrypted_thumbnail = upload::get_data( + &download_agent, + &format!("{}/{}.bin", server, image.thumb_url), + 7680_000, + &mut download_buffer + ).expect("Failed to retrieve image data"); + let decrypted_thumb = crypto::decrypt( + &key, + encrypted_thumbnail, + &mut decrypt_buffer + ).expect("Invalid image data referenced by index or bad key in index"); + dest_file.write_all(&decrypted_thumb).expect("Failed to write to disk"); + } } diff --git a/src/parse.rs b/src/parse.rs index 817375c..1e276ac 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use argh_derive::FromArgs; #[derive(FromArgs)] @@ -53,4 +55,10 @@ pub struct DownloadArgs { /// https://0x0.st/asdj.bin#omONdEzrY6SfdBgHn/2P6yG33PeIhuj3/SGm/lDhd2U= /// the encryption key is omONdEzrY6SfdBgHn/2P6yG33PeIhuj3/SGm/lDhd2U= pub key: String, + + #[argh(option, short='o')] + /// the directory to put the new files into + /// + /// A directory will be generated based on the name of the gallery if this is not set + pub output: Option, }