From b0035a511b13b03c4c73b0cfad488dbab541e01e Mon Sep 17 00:00:00 2001 From: A Farzat Date: Tue, 3 Mar 2026 10:28:20 +0300 Subject: Add file download logic All files in file_entries are downloaded according to their full_path. --- src/epub.rs | 34 ++++++++++++++++++++++++++++++++++ src/main.rs | 11 +++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/epub.rs 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 = chapters.into_iter().map(|c| (c.ourn.clone(), c)).collect(); -- cgit v1.2.3-70-g09d2