use std::{fs::OpenOptions, io::Write, path::PathBuf, process::exit}; use chrono::prelude::Local; use clap::Args; use epub_builder::{EpubBuilder, EpubContent, ReferenceType, ZipLibrary}; use file_system_crap::convert_path_to_os_specific; use url::Url; mod book; mod constants; mod file_system_crap; mod html; mod http; mod misc; /// struct that corresponds to arguments for Audiobook generation. #[derive(Args, Debug)] pub struct AudiobookArgs { /// Disable the generation of chapter titles in the audio file. Useful to avoid chapter titles appearing twice. #[arg(short, long)] pub no_chapter_titles: bool, /// Split the novel into multiple audio files by chapter. #[arg(short, long)] pub split_novel_by_chapters: bool, } /// struct that corresponds to arguments for Epub generation. #[derive(Args, Debug)] pub struct EpubArgs { /// Disable the inclusion of images. /// Will speed up epub generation and significantly decrease epub size. #[arg(short, long)] pub no_images: bool, } /// struct that corresponds to arguments for Html generation. #[derive(Args, Debug)] pub struct HtmlArgs { } /// struct that corresponds to arguments for Markdown generation. #[derive(Args, Debug)] pub struct MarkdownArgs { /// Disable the generation of chapter titles. Useful to avoid chapter titles appearing twice. #[arg(short, long)] pub no_chapter_titles: bool, /// Disables the inclusion of html image tags in the markdown. #[arg(short='i', long)] pub no_image_tags: bool, } /// Generate an audiobook from the given arguments, url, & outputs it to the output directory. /// /// This function DOES NOT do any error checking on the Url or output directory & WILL panic if they are wrong. /// Make sure the Url is valid and the output directory is writable BEFORE passing them to this. pub fn generate_audiobook(audiobook_args: AudiobookArgs, book_url: Url, output_directory: PathBuf) { eprintln!("This is not implemented yet."); } /// Generate an epub file from the given arguments, url, & outputs it to the output directory. /// /// This function DOES NOT do any error checking on the Url or output directory & WILL panic if they are wrong. /// Make sure the Url is valid and the output directory is writable BEFORE passing them to this. pub fn generate_epub(epub_args: EpubArgs, book_url: Url, output_directory: PathBuf) { // Until xhtml is working on MacOS this notice & exit code will remain. // See file_system_crap::setup_html2xhtml() for current status on MacOS support for this mode. #[cfg(target_os = "macos")] { eprint!("Error! This mode does not currently support MacOS. Try either html mode or markdown mode."); exit(1); } let book = book::Book::new(book_url); // Initialize the epub builder. let mut epub_builder = EpubBuilder::new(ZipLibrary::new().unwrap()).unwrap(); // Add author and title metadata. epub_builder.stylesheet(constants::EPUB_CSS.as_bytes()).unwrap(); // Use the epub_css in the constants.rs file. epub_builder .metadata("author", &book.author) .expect("Unable to add author metadata"); epub_builder .metadata("title", &book.title) .expect("Unable to add title metadata"); // Download the cover image & add it to the epub. let cover_image = http::get_response(book.cover_image_url).get_bytes().to_vec(); epub_builder.add_cover_image("cover.jpeg", cover_image.as_slice(), "image/jpeg").expect("Unable to add cover image."); // Generate the cover xhtml. let cover_xhtml = format!( r#"
"#, book.book_url, book.title, book.author, chrono::Local::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, false) ); let cover_xhtml = format!("{0}{cover_xhtml}{1}", constants::EPUB_XML_HEAD, constants::EPUB_XML_TAIL); // Add the cover xhtml to the epub. epub_builder.add_content( EpubContent::new("title.xhtml", cover_xhtml.as_bytes()) .title("Cover") .reftype(ReferenceType::Cover), ).expect("Unable to add cover"); // Add a table of contents after the cover page. epub_builder.inline_toc(); // Setup html2xhtml on the operating system. file_system_crap::setup_html2xhtml(); // TODO! Generate the epub body, deal with images etc etc. You know pickup from last night etc etc. // Finish setup_html2xhtml() first though dummy. // Generate the finished epub data as a byte vector. let mut finished_epub: Vec