import os
import datetime
import tempfile
import jinja2
from pykindle import items as _items
from pykindle import readers as _readers
[docs]class Book(list):
"""
This is a base class.
You should extend it, rather than use it directly.
See MagazineBook.
This class is inherited from python list class.
You can use all list functions.
Required attributes: None
Alternative attributes: title, language, uid, creator, publisher, subject, author, date, description
"""
def __init__(self):
super(Book, self).__init__()
self.title = 'Auto Generted by PyKindle'
self.language = 'zh-cn'
self.uid = '0000000000'
self.creator = 'PyKindle'
self.publisher = 'https://github.com/panhaoyu/pykindle'
self.subject = 'PyKindle'
self.author = 'Yourself'
self.date = datetime.datetime.now().strftime('%Y-%m-%d')
self.description = 'Auto generated by pykindle. You can get more information at our website: https://github.com/panhaoyu/pykindle.'
self._ncx = None
self._jinja = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(os.path.relpath(__file__)), 'templates')))
def _write_items(self, directory):
for item in self:
item.write(directory)
self._ncx.write(directory)
def _write_opf(self, directory):
content = self._jinja.get_template('magazine.opf').render({
'title': self.title, 'language': self.language, 'uid': self.uid, 'creator': self.creator,
'publisher': self.publisher, 'subject': self.subject, 'date': self.date, 'description': self.description,
'cover_image_url': self._cover_image_url, 'ncx': self._ncx, 'items': self, 'articles': self._articles
})
with open(os.path.join(directory, 'index.opf'), mode='w', encoding='utf-8') as file:
file.write(content)
def _generate_ncx(self):
self._ncx = _items.MagazineNcxItem()
self._ncx.id = 'ncx'
self._ncx.path = 'toc.ncx'
self._ncx.title = self.title
self._ncx.author = self.author
categories = dict()
for item in self:
category = categories.setdefault(item.category, list())
category.append(item)
self._ncx.categories = list(categories.items())
def _generate_book(self, directory):
opf_file = os.path.join(directory, 'index.opf')
os.system('kindlegen {} -o output.mobi'.format(opf_file))
output_path = os.path.join(directory, 'output.mobi')
if not os.path.exists(output_path):
raise ValueError('Mobi file generated failed. Please raise an issue.')
with open(output_path, mode='rb') as file:
content = file.read()
return content
@property
def _cover_image_url(self):
for item in self:
if isinstance(item, _items.CoverImageItem):
return item.href
@property
def _articles(self):
return [item for item in self if isinstance(item, _items.ArticleItem)]
def _generate_article_id(self):
for index, item in enumerate(self):
item.id = str(index)
def create(self):
with tempfile.TemporaryDirectory() as directory:
self._generate_article_id()
self._generate_ncx()
self._write_opf(directory)
self._write_items(directory)
content = self._generate_book(directory)
return content
[docs]class NormalBook(Book):
"""
This class represents a normal book.
Normal means the book has a toc, and readers will read from first paragraph to last paragraph.
"""
pass
[docs]class MagazineBook(Book):
pass
__all__ = ['Book', 'MagazineBook', 'NormalBook']