diff --git a/Cargo.lock b/Cargo.lock index 7445bcb..4310d61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1195,6 +1195,7 @@ dependencies = [ "prometheus", "regex", "reqwest", + "serde", "serde_json", "stderrlog", "structopt", diff --git a/Cargo.toml b/Cargo.toml index 8840465..24e09db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ stderrlog = "0.4.3" structopt = "0.3.9" yup-oauth2 = "^3.1" warp = "0.1" +serde = { version = "1.0.104", features = ["derive"] } [dependencies.prometheus] features = ["process"] diff --git a/src/library.rs b/src/library.rs new file mode 100644 index 0000000..d7a3ebf --- /dev/null +++ b/src/library.rs @@ -0,0 +1,84 @@ +use std::fs; +use std::fs::File; +use std::io; +use std::path::Path; +use std::path::PathBuf; + +use google_photoslibrary1 as photos; +use log::info; +use photos::schemas::Album; +use photos::schemas::MediaItem; + +pub struct Library { + root: PathBuf, + originals_dir: PathBuf, +} + +impl Library { + pub fn new(root: PathBuf) -> io::Result { + let lib = Library { + originals_dir: root.join("images").join("originals"), + root, + }; + if !lib.originals_dir.exists() { + info!( + "create originals dir {}", + &lib.originals_dir.to_string_lossy() + ); + fs::create_dir_all(&lib.originals_dir)?; + } + Ok(lib) + } + pub fn create_album_index(&self, albums: &Vec) -> io::Result<()> { + // Serialize it to a JSON string. + let j = serde_json::to_string(albums)?; + + let path = self.root.join("albums.json"); + info!("saving {}", path.to_string_lossy()); + fs::write(path, j) + } + pub fn create_album>( + &self, + album_id: P, + media_items: &Vec, + ) -> io::Result<()> { + let album_dir = self.root.join(album_id); + if !album_dir.exists() { + info!("making album directory {}", album_dir.to_string_lossy()); + fs::create_dir_all(&album_dir)?; + } + let j = serde_json::to_string(&media_items)?; + let path = album_dir.join("album.json"); + info!("saving {}", path.to_string_lossy()); + fs::write(path, j) + } + pub fn download_image( + &self, + filename: &str, + media_items_id: &str, + base_url: &str, + ) -> Result> { + // Put images from all albums in common directory. + let image_path = self.originals_dir.join(media_items_id); + if image_path.exists() { + info!( + "Skipping already downloaded {} @ {}", + &filename, + image_path.to_string_lossy() + ); + } else { + let download_path = image_path.with_extension("download"); + let url = format!("{}=d", base_url); + let mut r = reqwest::blocking::get(&url)?; + let mut w = File::create(&download_path)?; + let _n = io::copy(&mut r, &mut w)?; + info!( + "Rename {} -> {}", + download_path.to_string_lossy(), + image_path.to_string_lossy() + ); + fs::rename(download_path, &image_path)?; + } + Ok(image_path) + } +} diff --git a/src/main.rs b/src/main.rs index 205afb3..7ae6fd7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,7 @@ use reqwest; use structopt::StructOpt; use yup_oauth2::{Authenticator, InstalledFlow}; +mod library; mod web; #[derive(Debug, StructOpt)] @@ -198,67 +199,30 @@ fn sync_albums( title_filter: Option, output_dir: PathBuf, ) -> Result<(), Box> { - // Put images from all albums in common directory. - let image_dir = output_dir.join("images"); - if !image_dir.exists() { - fs::create_dir_all(&image_dir)?; - } + let lib = library::Library::new(output_dir)?; let albums = list_albums(client, title_filter)?; + lib.create_album_index(&albums)?; for a in &albums { let album_id = a.id.as_ref().expect("unset album id").to_string(); - let album_dir = output_dir.join(&album_id); - if !album_dir.exists() { - info!("making album directory {}", album_dir.to_string_lossy()); - fs::create_dir_all(&album_dir)?; - } - - let album = search_media_items(client, &album_id)?; - for (i, mi) in album.iter().enumerate() { + let media_items = search_media_items(client, &album_id)?; + lib.create_album(&album_id, &media_items)?; + for (i, mi) in media_items.iter().enumerate() { let mi_id = mi.id.as_ref().expect("unset media item id").to_string(); let filename = mi .filename .as_ref() .map_or("NO_FILENAME".to_string(), |s| s.to_string()); - let image_path = image_dir.join(mi_id); - if image_path.exists() { - info!( - "Skipping already downloaded {} @ {}", - &filename, - image_path.to_string_lossy() - ); - } else { - let download_path = image_path.with_extension("download"); - info!( - "({}/{}) Downloading {} -> {}", - i + 1, - &album.len(), - &filename, - download_path.to_string_lossy() - ); - let base_url = mi.base_url.as_ref().expect("missing base_url"); - let url = format!("{}=d", base_url); - let mut r = reqwest::blocking::get(&url)?; - let mut w = File::create(&download_path)?; - let _n = io::copy(&mut r, &mut w)?; - info!( - "Rename {} -> {}", - download_path.to_string_lossy(), - image_path.to_string_lossy() - ); - fs::rename(download_path, &image_path)?; - } + let base_url = mi.base_url.as_ref().expect("missing base_url"); + let image_path = lib.download_image(&filename, &mi_id, &base_url)?; + info!( + "({}/{}) Downloading {} -> {}", + i + 1, + &media_items.len(), + &filename, + image_path.to_string_lossy() + ); } - let j = serde_json::to_string(&album)?; - let path = album_dir.join("album.json"); - info!("saving {}", path.to_string_lossy()); - fs::write(path, j)?; } - // Serialize it to a JSON string. - let j = serde_json::to_string(&albums)?; - - let path = output_dir.join("albums.json"); - info!("saving {}", path.to_string_lossy()); - fs::write(path, j)?; Ok(()) }