Compare commits

...

1 Commits

Author SHA1 Message Date
7a31a73e60 Add search iterator 2020-02-07 09:57:28 -08:00

View File

@ -2,8 +2,8 @@ use std::error::Error;
use std::path::PathBuf;
use google_api_auth;
use google_photoslibrary1;
use google_photoslibrary1::schemas::SearchMediaItemsRequest;
use google_photoslibrary1 as photos;
use photos::schemas::{MediaItem, SearchMediaItemsRequest};
use regex::Regex;
use structopt::StructOpt;
use yup_oauth2::{Authenticator, InstalledFlow};
@ -43,7 +43,7 @@ struct Opt {
fn new_client(
credentials: &PathBuf,
token_cache: &PathBuf,
) -> Result<google_photoslibrary1::Client, Box<dyn Error>> {
) -> Result<photos::Client, Box<dyn Error>> {
let secret = yup_oauth2::read_application_secret(credentials)?;
// Create an authenticator that uses an InstalledFlow to authenticate. The
@ -58,53 +58,87 @@ fn new_client(
.build()
.unwrap();
let scopes = vec!["https://www.googleapis.com/auth/photoslibrary.readonly".to_string()];
let scopes = vec!["https://www.googleapis.com/auth/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<dyn Error>> {
let mut page_token = None;
let mut total = 0;
struct SearchIter<'a> {
client: &'a photos::Client,
items: ::std::vec::IntoIter<MediaItem>,
finished: bool,
req: SearchMediaItemsRequest,
}
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<MediaItem, photos::Error>;
fn next(&mut self) -> Option<Result<MediaItem, photos::Error>> {
loop {
let resp = client
if let Some(v) = self.items.next() {
return Some(Ok(v));
}
if self.finished {
return None;
}
let resp = match self
.client
.media_items()
.search(SearchMediaItemsRequest {
.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<dyn Error>> {
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),
page_token,
..Default::default()
})
.execute_with_all_fields()?;
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 {
let mi = mi?;
total += 1;
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(());
}
}
Ok(())
}
fn list_albums(
client: google_photoslibrary1::Client,
title_filter: Option<Regex>,
) -> Result<(), Box<dyn Error>> {
fn list_albums(client: photos::Client, title_filter: Option<Regex>) -> Result<(), Box<dyn Error>> {
for album in client
.shared_albums()
.list()