Merge branch 'master' of https://git.z.xinu.tv/wathiede/photosync
This commit is contained in:
commit
3ad5c4f706
117
src/main.rs
117
src/main.rs
@ -3,11 +3,9 @@ use std::fs;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use google_api_auth;
|
use google_api_auth;
|
||||||
use google_photoslibrary1;
|
use google_photoslibrary1 as photos;
|
||||||
use google_photoslibrary1::schemas::Album;
|
use log::{debug, info};
|
||||||
use google_photoslibrary1::schemas::SearchMediaItemsRequest;
|
use photos::schemas::{Album, MediaItem, SearchMediaItemsRequest};
|
||||||
use log::debug;
|
|
||||||
use log::info;
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use yup_oauth2::{Authenticator, InstalledFlow};
|
use yup_oauth2::{Authenticator, InstalledFlow};
|
||||||
@ -54,7 +52,7 @@ struct Opt {
|
|||||||
fn new_client(
|
fn new_client(
|
||||||
credentials: &PathBuf,
|
credentials: &PathBuf,
|
||||||
token_cache: &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)?;
|
let secret = yup_oauth2::read_application_secret(credentials)?;
|
||||||
|
|
||||||
// Create an authenticator that uses an InstalledFlow to authenticate. The
|
// Create an authenticator that uses an InstalledFlow to authenticate. The
|
||||||
@ -69,51 +67,88 @@ fn new_client(
|
|||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.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);
|
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(
|
struct SearchIter<'a> {
|
||||||
client: &google_photoslibrary1::Client,
|
client: &'a photos::Client,
|
||||||
album_id: String,
|
items: ::std::vec::IntoIter<MediaItem>,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
finished: bool,
|
||||||
let mut page_token = None;
|
req: SearchMediaItemsRequest,
|
||||||
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()?;
|
|
||||||
|
|
||||||
let media_items = resp.media_items.ok_or("no results")?;
|
impl<'a> SearchIter<'a> {
|
||||||
println!("got ({}) items", media_items.len());
|
fn new(client: &'a photos::Client, req: SearchMediaItemsRequest) -> Self {
|
||||||
total += media_items.len();
|
SearchIter {
|
||||||
for mi in media_items {
|
client,
|
||||||
println!(
|
items: Vec::new().into_iter(),
|
||||||
"{} {}",
|
finished: false,
|
||||||
mi.id.unwrap_or("NO ID".to_string()),
|
req,
|
||||||
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> Iterator for SearchIter<'a> {
|
||||||
|
type Item = Result<MediaItem, photos::Error>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Result<MediaItem, photos::Error>> {
|
||||||
|
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<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),
|
||||||
|
..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(
|
fn sync_albums(
|
||||||
client: &google_photoslibrary1::Client,
|
client: &photos::Client,
|
||||||
title_filter: Option<Regex>,
|
title_filter: Option<Regex>,
|
||||||
output_dir: PathBuf,
|
output_dir: PathBuf,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
@ -151,7 +186,7 @@ fn print_albums(albums: Vec<Album>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn list_albums(
|
fn list_albums(
|
||||||
client: &google_photoslibrary1::Client,
|
client: &photos::Client,
|
||||||
title_filter: Option<Regex>,
|
title_filter: Option<Regex>,
|
||||||
) -> Result<Vec<Album>, Box<dyn Error>> {
|
) -> Result<Vec<Album>, Box<dyn Error>> {
|
||||||
Ok(client
|
Ok(client
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user