import os from ebooklib import epub from fpdf import FPDF import markdown class BookBuilder: def __init__(self, title, author, description="", cover_image=None): self.title = title self.author = author self.description = description self.cover_image = cover_image self.chapters = [] # Fetch Business Metadata from Environment self.business_name = os.environ.get("BUSINESS_NAME", "Fair Dinkum Publishing") self.abn = os.environ.get("BUSINESS_ABN", "63 590 716 023") self.owner = os.environ.get("BUSINESS_OWNER", "BRETT SJOBERG") def add_chapter(self, title, content): self.chapters.append({"title": title, "content": content}) def generate_epub(self, output_path): book = epub.EpubBook() book.set_identifier(f"fdp-{abs(hash(self.title))}") book.set_title(self.title) book.set_language("en") book.add_author(self.author) book.add_metadata("DC", "publisher", self.business_name) book.add_metadata("DC", "description", self.description) book.add_metadata("DC", "rights", f"Copyright (c) 2026 {self.owner}. ABN: {self.abn}") spine = ["nav"] # Add Cover Image if provided if self.cover_image and os.path.exists(self.cover_image): with open(self.cover_image, 'rb') as img_file: content = img_file.read() img_ext = os.path.splitext(self.cover_image)[1][1:] book.set_cover("cover.jpg", content) # Add Copyright Page copy_page = epub.EpubHtml(title="Copyright", file_name="copyright.xhtml", lang="en") copy_page.content = f"""

Copyright

{self.title}

Published by {self.business_name}

Owner: {self.owner}

ABN: {self.abn}

All rights reserved. No part of this publication may be reproduced without permission.

""" book.add_item(copy_page) spine.append(copy_page) for i, ch in enumerate(self.chapters): chapter = epub.EpubHtml(title=ch["title"], file_name=f"chap_{i+1}.xhtml", lang="en") # Convert Markdown to HTML content_html = markdown.markdown(ch["content"]) chapter.content = f"

{ch['title']}

{content_html}" book.add_item(chapter) spine.append(chapter) book.add_item(epub.EpubNav()) book.add_item(epub.EpubNcx()) book.spine = spine epub.write_epub(output_path, book, {}) return output_path def generate_pdf(self, output_path): pdf = FPDF() pdf.set_auto_page_break(auto=True, margin=15) # Title Page pdf.add_page() if self.cover_image and os.path.exists(self.cover_image): # Try to fit cover image on first page pdf.image(self.cover_image, x=10, y=10, w=190) pdf.add_page() pdf.set_font("Arial", "B", 24) pdf.cell(200, 40, self.title, ln=True, align="C") pdf.set_font("Arial", "I", 16) pdf.cell(200, 10, f"By {self.author}", ln=True, align="C") pdf.ln(20) # Copyright Info pdf.set_font("Arial", "", 10) pdf.cell(0, 10, f"Published by {self.business_name}", ln=True, align="C") pdf.cell(0, 10, f"ABN: {self.abn}", ln=True, align="C") pdf.ln(20) # Chapters for ch in self.chapters: pdf.add_page() pdf.set_font("Arial", "B", 18) pdf.cell(0, 10, ch["title"], ln=True) pdf.ln(10) # Use write_html to handle basic markdown-to-html conversion for FPDF # FPDF2 supports basic HTML tags with write_html html_content = markdown.markdown(ch["content"]) pdf.set_font("Arial", "", 12) pdf.write_html(html_content) # Footer on every page pdf.set_y(-15) pdf.set_font("Arial", "I", 8) pdf.cell(0, 10, f"{self.business_name} - ABN {self.abn} - Page {pdf.page_no()}", align="C") pdf.output(output_path) return output_path def create_ebook_files(title, author, content_list, base_name="ebook", cover_image=None): """ Helper to create both formats. content_list: List of dicts with 'title' and 'content'. """ builder = BookBuilder(title, author, cover_image=cover_image) for item in content_list: builder.add_chapter(item["title"], item["content"]) os.makedirs("exports", exist_ok=True) epub_file = builder.generate_epub(f"exports/{base_name}.epub") pdf_file = builder.generate_pdf(f"exports/{base_name}.pdf") return epub_file, pdf_file