import contextlib
import os
import shutil
import tempfile
import xml.etree.ElementTree as ET
from typing import Tuple, Union
from epy_reader.ebooks.epub import Epub
from epy_reader.models import BookMetadata
from epy_reader.tools import unpack_kindle_book
class Mobi(Epub):
def __init__(self, filemobi: str):
self.path = os.path.abspath(filemobi)
self.file = tempfile.mkdtemp(prefix="epy-")
# populate these attribute
# by calling self.initialize()
self.root_filepath: str
self.root_dirpath: str
def get_meta(self) -> BookMetadata:
# why self.file.read(self.root_filepath) problematic
with open(os.path.join(self.root_dirpath, "content.opf")) as f:
content_opf = ET.parse(f) # .getroot()
return Epub._get_metadata(content_opf)
def initialize(self) -> None:
assert isinstance(self.file, str)
with contextlib.redirect_stdout(None):
unpack_kindle_book(self.path, self.file, epubver="A", use_hd=True)
# TODO: add cleanup here
self.root_dirpath = os.path.join(self.file, "mobi7")
self.toc_path = os.path.join(self.root_dirpath, "toc.ncx")
version = "2.0"
with open(os.path.join(self.root_dirpath, "content.opf")) as f:
content_opf = ET.parse(f) # .getroot()
contents = Epub._get_contents(content_opf)
self.contents = tuple(os.path.join(self.root_dirpath, content) for content in contents)
with open(self.toc_path) as f:
toc = ET.parse(f).getroot()
self.toc_entries = Epub._get_tocs(toc, version, contents) # *self.contents (absolute path)
def get_raw_text(self, content_path: Union[str, ET.Element]) -> str:
assert isinstance(content_path, str)
with open(content_path, encoding="utf8") as f:
content = f.read()
# return content.decode("utf-8")
return content
def get_img_bytestr(self, impath: str) -> Tuple[str, bytes]:
# TODO: test on windows
# if impath "Images/asdf.png" is problematic
image_abspath = os.path.join(self.root_dirpath, impath)
image_abspath = os.path.normpath(image_abspath) # handle crossplatform path
with open(image_abspath, "rb") as f:
src = f.read()
return impath, src
def cleanup(self) -> None:
assert isinstance(self.file, str)
shutil.rmtree(self.file)
return