diff options
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/src/main.rs b/src/main.rs index 165d6be..30f08ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ mod models; use anyhow::{Context, Result}; use clap::Parser; use http_client::build_authenticated_client; -use models::{EpubResponse, SearchResponse}; +use models::{Chapter, EpubResponse, FileEntry, Paginated, SearchResponse}; use reqwest::Client; /// Download and generate an EPUB from Safari Books Online. @@ -50,6 +50,34 @@ async fn fetch_epub_data(client: &Client, bookid: &str) -> Result<EpubResponse> Ok(response) } +/// Fetch a paginated API. +async fn fetch_all_pages<T>(client: &reqwest::Client, mut url: String) -> Result<Vec<T>> +where + T: serde::de::DeserializeOwned, +{ + let mut items = Vec::new(); + loop { + // GET current URL and deserialize into Paginated<T>. + let response = client + .get(&url) + .send() + .await? + .error_for_status()? + .json::<Paginated<T>>() + .await + .context("Failed to deserialize API response.")?; + // Extend items with the page's results. + items.extend(response.results); + // Set url to next page if available, else break. + if let Some(next) = response.next { + url = next; + } else { + break; + } + } + Ok(items) +} + #[tokio::main] async fn main() -> Result<()> { // Parse the command line arguments @@ -81,5 +109,9 @@ async fn main() -> Result<()> { println!("Resources URL: {}", epub_data.files); println!("------------------\n"); + println!("Fetching book structure..."); + let chapters: Vec<Chapter> = fetch_all_pages(&client, epub_data.chapters.clone()).await?; + let file_entries: Vec<FileEntry> = fetch_all_pages(&client, epub_data.files.clone()).await?; + Ok(()) } |
