diff --git a/src/main.rs b/src/main.rs index 9cd2adc..45e7f36 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,11 +3,9 @@ use std::fs; use std::path::PathBuf; use google_api_auth; -use google_photoslibrary1; -use google_photoslibrary1::schemas::Album; -use google_photoslibrary1::schemas::SearchMediaItemsRequest; -use log::debug; -use log::info; +use google_photoslibrary1 as photos; +use log::{debug, info}; +use photos::schemas::{Album, MediaItem, SearchMediaItemsRequest}; use regex::Regex; use structopt::StructOpt; use yup_oauth2::{Authenticator, InstalledFlow}; @@ -54,7 +52,7 @@ struct Opt { fn new_client( credentials: &PathBuf, token_cache: &PathBuf, -) -> Result> { +) -> Result> { let secret = yup_oauth2::read_application_secret(credentials)?; // Create an authenticator that uses an InstalledFlow to authenticate. The @@ -69,51 +67,88 @@ fn new_client( .build() .unwrap(); - let scopes = vec![google_photoslibrary1::scopes::PHOTOSLIBRARY_READONLY]; + let scopes = vec![photos::scopes::PHOTOSLIBRARY_READONLY]; let auth = google_api_auth::yup_oauth2::from_authenticator(auth, scopes); - Ok(google_photoslibrary1::Client::new(auth)) + Ok(photos::Client::new(auth)) } -fn search_media_items( - client: &google_photoslibrary1::Client, - album_id: String, -) -> Result<(), Box> { - let mut page_token = None; - let mut total = 0; - loop { - let resp = client - .media_items() - .search(SearchMediaItemsRequest { - album_id: Some(album_id.clone()), - // 100 is the documented max. - page_size: Some(100), - page_token, - ..Default::default() - }) - .execute_with_all_fields()?; +struct SearchIter<'a> { + client: &'a photos::Client, + items: ::std::vec::IntoIter, + finished: bool, + req: SearchMediaItemsRequest, +} - let media_items = resp.media_items.ok_or("no results")?; - println!("got ({}) items", media_items.len()); - total += media_items.len(); - for mi in media_items { - println!( - "{} {}", - mi.id.unwrap_or("NO ID".to_string()), - mi.filename.unwrap_or("NO FILENAME".to_string()) - ); - } - page_token = resp.next_page_token; - if page_token.is_none() { - println!("({}) items total", total); - return Ok(()); +impl<'a> SearchIter<'a> { + fn new(client: &'a photos::Client, req: SearchMediaItemsRequest) -> Self { + SearchIter { + client, + items: Vec::new().into_iter(), + finished: false, + req, } } } +impl<'a> Iterator for SearchIter<'a> { + type Item = Result; + + fn next(&mut self) -> Option> { + loop { + if let Some(v) = self.items.next() { + return Some(Ok(v)); + } + if self.finished { + return None; + } + let resp = match self + .client + .media_items() + .search(self.req.clone()) + .execute_with_default_fields() + { + Ok(resp) => resp, + Err(err) => return Some(Err(err)), + }; + if resp.next_page_token.is_none() { + self.finished = true; + } + self.req.page_token = resp.next_page_token; + if let Some(items) = resp.media_items { + self.items = items.into_iter(); + } + } + } +} + +fn search_media_items(client: &photos::Client, album_id: String) -> Result<(), Box> { + let mut total = 0; + let media_items = SearchIter::new( + &client, + SearchMediaItemsRequest { + album_id: Some(album_id.clone()), + // 100 is the documented max. + page_size: Some(100), + ..Default::default() + }, + ); + for mi in media_items { + let mi = mi?; + total += 1; + println!( + "{} {}", + mi.id.unwrap_or("NO ID".to_string()), + mi.filename.unwrap_or("NO FILENAME".to_string()) + ); + } + println!("({}) items total", total); + Ok(()) +} + fn sync_albums( - client: &google_photoslibrary1::Client, + client: &photos::Client, title_filter: Option, output_dir: PathBuf, ) -> Result<(), Box> { @@ -151,7 +186,7 @@ fn print_albums(albums: Vec) { } fn list_albums( - client: &google_photoslibrary1::Client, + client: &photos::Client, title_filter: Option, ) -> Result, Box> { Ok(client