aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA Farzat <a@farzat.xyz>2026-03-03 10:28:20 +0300
committerA Farzat <a@farzat.xyz>2026-03-03 11:05:07 +0300
commitb0035a511b13b03c4c73b0cfad488dbab541e01e (patch)
tree1f57a0bc5403b59259bb92c65493663bb5b59382
parent859700794abece7d5a90896a87fe012164d9fc0e (diff)
downloadoreilly-epub-b0035a511b13b03c4c73b0cfad488dbab541e01e.tar.gz
oreilly-epub-b0035a511b13b03c4c73b0cfad488dbab541e01e.zip
Add file download logic
All files in file_entries are downloaded according to their full_path.
-rw-r--r--src/epub.rs34
-rw-r--r--src/main.rs11
2 files changed, 43 insertions, 2 deletions
diff --git a/src/epub.rs b/src/epub.rs
new file mode 100644
index 0000000..0c0bc74
--- /dev/null
+++ b/src/epub.rs
@@ -0,0 +1,34 @@
+use crate::models::FileEntry;
+use anyhow::Result;
+use reqwest::Client;
+use std::path::Path;
+use tokio::{
+ fs::{self, File},
+ io::AsyncWriteExt,
+};
+
+pub async fn download_all_files(
+ client: &Client,
+ file_entries: &[FileEntry],
+ dest_root: &Path,
+) -> Result<()> {
+ for entry in file_entries {
+ let dest_path = dest_root.join(&entry.full_path);
+
+ if let Some(parent_dir) = dest_path.parent() {
+ fs::create_dir_all(parent_dir).await?;
+ }
+
+ let mut file = File::create(dest_path).await?;
+ let bytes = client
+ .get(&entry.url)
+ .send()
+ .await?
+ .error_for_status()?
+ .bytes()
+ .await?;
+
+ file.write_all(&bytes).await?;
+ }
+ Ok(())
+}
diff --git a/src/main.rs b/src/main.rs
index 4f28d52..ed73ec7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,12 +1,15 @@
+mod epub;
mod http_client;
mod models;
use std::collections::HashMap;
+use std::path::Path;
+use crate::epub::download_all_files;
+use crate::http_client::build_authenticated_client;
+use crate::models::{Chapter, EpubResponse, FileEntry, Paginated, SpineItem, TocNode};
use anyhow::{Context, Result, ensure};
use clap::Parser;
-use http_client::build_authenticated_client;
-use models::{Chapter, EpubResponse, FileEntry, Paginated, SpineItem, TocNode};
use reqwest::Client;
/// Download and generate an EPUB from Safari Books Online.
@@ -115,6 +118,10 @@ async fn main() -> Result<()> {
.find(|f| f.filename_ext == ".opf" && f.media_type == "application/oebps-package+xml")
.context("No OPF file with the correct MIME type was found.")?;
+ let dest_root = format!("Books/{}/epub_root", args.bookid);
+ let dest_root = Path::new(&dest_root);
+ download_all_files(&client, &file_entries, dest_root).await?;
+
// Sanity check: Every entry in spine exists in chapters.
let chapters: HashMap<String, Chapter> =
chapters.into_iter().map(|c| (c.ourn.clone(), c)).collect();