1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
use std::io::Read; use anyhow::anyhow; use dropbox_sdk::files::{ self, FileMetadata, FolderMetadata, ListFolderArg, ListFolderContinueArg, ListFolderCursor, Metadata, PathROrId, SharedLink, }; use dropbox_sdk::sharing::{self, GetSharedLinkFileArg, Path}; use crate::authorizer::Token; use crate::convert_dbx_err; use crate::hyper_client::HyperClient; use crate::Result; #[derive(Debug)] pub struct Dropbox { client: HyperClient, } impl Dropbox { pub fn new(token: Token) -> Self { let client = HyperClient::new(token.access_token); Self { client } } pub fn list_all_folders<P: Into<PathROrId>>( &self, path: P, shared_link_url: Option<&str>, ) -> Result<Vec<FolderMetadata>> { let folders = self .list_folder(path, shared_link_url)? .into_iter() .filter_map(|meta| match meta { Metadata::Folder(folder_meta) => Some(folder_meta), _ => None, }) .collect(); Ok(folders) } pub fn list_all_files<P: Into<PathROrId>>( &self, path: P, shared_link_url: Option<&str>, ) -> Result<Vec<FileMetadata>> { let files = self .list_folder(path, shared_link_url)? .into_iter() .filter_map(|meta| match meta { Metadata::File(file_meta) => Some(file_meta), _ => None, }) .collect(); Ok(files) } fn list_folder<P: Into<PathROrId>>( &self, path: P, shared_link_url: Option<&str>, ) -> Result<Vec<Metadata>> { let mut arg = ListFolderArg::new(path.into()); if let Some(shared_link_url) = shared_link_url { let shared_link = SharedLink::new(shared_link_url.to_owned()); arg = arg.with_shared_link(Some(shared_link)); } let res = files::list_folder(&self.client, &arg).map_err(convert_dbx_err)??; let mut folders = res.entries; if res.has_more { self.list_folder_continue(res.cursor, &mut folders)?; } Ok(folders) } fn list_folder_continue( &self, cursor: ListFolderCursor, folders: &mut Vec<Metadata>, ) -> Result<()> { let arg = ListFolderContinueArg { cursor }; let res = files::list_folder_continue(&self.client, &arg).map_err(convert_dbx_err)??; folders.extend(res.entries.into_iter()); if res.has_more { self.list_folder_continue(res.cursor, folders)?; } Ok(()) } pub fn get_shared_link_file<T: Into<String>>( &self, url: T, path: Path, ) -> Result<Box<dyn Read>> { let arg = GetSharedLinkFileArg::new(url.into()).with_path(Some(path.clone())); let res = sharing::get_shared_link_file(&self.client, &arg, None, None) .map_err(convert_dbx_err)??; match res.body { Some(body) => Ok(body), _ => Err(anyhow!("Found empty body : {}", path)), } } }