diff --git a/src/main.rs b/src/main.rs index 33b34d7..cdacbd6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,7 +14,7 @@ use std::collections::HashMap; use std::time::{Instant, Duration}; use json::JsonValue; -use reqwest::{Client, RedirectPolicy}; +use reqwest::{Client, Response, RedirectPolicy}; use reqwest::header::{Cookie, Charset, SetCookie}; use reqwest::header::{ContentDisposition, DispositionType, DispositionParam}; use zip::ZipArchive; @@ -34,6 +34,8 @@ mod catalogs { // TODO: use clap for proper CLI // TODO: clippy +// TODO: replace unwraps with descriptive expects +// TODO: retry some things if sensible lazy_static! { static ref CLIENT: Client = { @@ -126,8 +128,11 @@ fn download_catalog(catalog_name: &str, out_dir: &Path, auth: &str) { presentations.len()); for (i, presentation) in presentations.iter().enumerate() { - println!("Downloading {}/{}: {}", i + 1, presentations.len(), presentation.name); - download_presentation(&presentation, out_dir, auth); + println!("Downloading {}/{}: {}", + i + 1, + presentations.len(), + presentation.name); + download_presentation(presentation, out_dir, auth); } } @@ -151,26 +156,46 @@ fn get_catalog_id(name: &str, auth: &str) -> String { } fn download_presentation(presentation: &Presentation, out_dir: &Path, auth: &str) { - let response = CLIENT.get(&presentation.download_url) - .header(construct_cookie(auth)) - .send() - .unwrap(); + fn try_download(presentation: &Presentation, auth: &str) -> Option<(Response, String)> { + let response = CLIENT.get(&presentation.download_url) + .header(construct_cookie(auth)) + .send() + .unwrap(); - let filename = { - let content_disposition: &ContentDisposition = response.headers().get().unwrap(); - assert_eq!(content_disposition.disposition, DispositionType::Attachment); - let mut name = None; - for param in &content_disposition.parameters { - match *param { - DispositionParam::Filename(ref charset, _, ref vec) => { - assert_eq!(&Charset::Ext("UTF-8".to_string()), charset); - name = Some(String::from_utf8(vec.to_vec()).unwrap()); + let filename = if let Some(content_disposition) = + response.headers().get::() { + assert_eq!(content_disposition.disposition, DispositionType::Attachment); + let mut name = None; + for param in &content_disposition.parameters { + match *param { + DispositionParam::Filename(ref charset, _, ref vec) => { + assert_eq!(&Charset::Ext("UTF-8".to_string()), charset); + name = Some(String::from_utf8(vec.to_vec()).unwrap()); + } + _ => continue, } - _ => continue, } + name.expect("Missing filename in ContentDisposition!") + } else { + return None; + }; + + Some((response, filename)) + } + + let mut tries = 0; + let mut tuple = None; + while tries < 8 { + let try = try_download(presentation, auth); + if try.is_some() { + tuple = try; } - name.expect("Missing filename in ContentDisposition!") - }; + tries += 1; + } + if tuple.is_none() { + panic!("Failed to get a proper response while trying to download presentation!"); + } + let (response, filename) = tuple.unwrap(); let mut path = PathBuf::from(out_dir); path.push(fix_filename(&filename));