dynasty 1.4.1

Dynasty Reader's CLI downloader
Documentation
use std::{
    fs::File,
    io::BufWriter,
    path::{Path, PathBuf},
};

use anyhow::Result;
use indicatif::ProgressBar;

use super::ArchivableChapter;

fn filename_from_path(path: &Path) -> &str {
    path.file_name().unwrap().to_str().unwrap()
}

fn create_file_writer(path: &Path) -> Result<BufWriter<File>> {
    Ok(File::create(path).map(BufWriter::new)?)
}

#[cfg(feature = "archive-zip")]
pub fn archive_zip(chapter: &ArchivableChapter, progress_bar: &ProgressBar) -> Result<PathBuf> {
    use std::io::{Read, Write};

    use zip::write::ZipWriter;

    let zip_path = chapter.path_with_extension("zip");
    let writer = create_file_writer(&zip_path)?;

    let mut zip = ZipWriter::new(writer);
    let mut buffer = Vec::new();
    for page_path in progress_bar.wrap_iter(chapter.pages.iter()) {
        let name = filename_from_path(page_path);

        zip.start_file(name, Default::default())?;
        let mut file = File::open(page_path)?;
        file.read_to_end(&mut buffer)?;
        zip.write_all(&*buffer)?;

        buffer.clear();
    }

    zip.finish()?;
    Ok(zip_path)
}

#[cfg(feature = "archive-zip")]
pub fn archive_cbz(chapter: &ArchivableChapter, progress_bar: &ProgressBar) -> Result<PathBuf> {
    use std::fs;

    let cbz_path = chapter.path_with_extension("cbz");
    let zip_path = archive_zip(chapter, progress_bar)?;
    fs::rename(&zip_path, &cbz_path)?;

    Ok(cbz_path)
}

#[cfg(feature = "archive-pdf")]
pub fn archive_pdf(chapter: &ArchivableChapter, progress_bar: &ProgressBar) -> Result<PathBuf> {
    use image::io::Reader as ImageReader;
    use printpdf::{Image, ImageTransform, Mm, PdfDocument};

    let pdf_path = chapter.path_with_extension("pdf");
    let mut writer = create_file_writer(&pdf_path)?;

    let pdf = PdfDocument::empty(chapter.filename());
    for page_path in progress_bar.wrap_iter(chapter.pages.iter()) {
        let image = ImageReader::open(&page_path)?
            .with_guessed_format()?
            .decode()?;
        let (width, height) = (image.width() / 12, image.height() / 12);

        let name = filename_from_path(page_path);
        let (page_index, layer_index) = pdf.add_page(Mm(width.into()), Mm(height.into()), name);
        let current_layer = pdf.get_page(page_index).get_layer(layer_index);

        let image = Image::from_dynamic_image(&image);
        image.add_to_layer(current_layer, ImageTransform::default());
    }

    progress_bar.set_position(progress_bar.position() - 1);
    pdf.save(&mut writer)?;
    Ok(pdf_path)
}

#[cfg(feature = "archive-tar")]
pub fn archive_tar(chapter: &ArchivableChapter, progress_bar: &ProgressBar) -> Result<PathBuf> {
    let tar_path = chapter.path_with_extension("tar");
    let writer = create_file_writer(&tar_path)?;

    let mut tar = tar::Builder::new(writer);
    for page_path in progress_bar.wrap_iter(chapter.pages.iter()) {
        let name = filename_from_path(page_path);

        let mut file = File::open(&page_path)?;
        tar.append_file(name, &mut file)?;
    }

    Ok(tar_path)
}

#[cfg(feature = "archive-tar")]
pub fn archive_cbt(chapter: &ArchivableChapter, progress_bar: &ProgressBar) -> Result<PathBuf> {
    use std::fs;

    let cbt_path = chapter.path_with_extension("cbt");
    let tar_path = archive_tar(chapter, progress_bar)?;
    fs::rename(&tar_path, &cbt_path)?;

    Ok(cbt_path)
}