mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Kobo driver: Automatically unkepubify books when exporting from the device
Also, allow adding the virtual books since nowadays some of them are DRM free. DRMed books will still give an error when attempting to add them to the library.
This commit is contained in:
parent
249c2d11a1
commit
9199cb6905
@ -26,11 +26,12 @@ from calibre.devices.kobo.books import Book, ImageWrapper, KTCollectionsBookList
|
||||
from calibre.devices.mime import mime_type_ext
|
||||
from calibre.devices.usbms.books import BookList, CollectionsBookList
|
||||
from calibre.devices.usbms.driver import USBMS
|
||||
from calibre.ebooks import DRMError
|
||||
from calibre.ebooks.metadata import authors_to_string
|
||||
from calibre.ebooks.metadata.book.base import Metadata
|
||||
from calibre.ebooks.metadata.utils import normalize_languages
|
||||
from calibre.prints import debug_print
|
||||
from calibre.ptempfile import PersistentTemporaryFile, better_mktemp
|
||||
from calibre.ptempfile import PersistentTemporaryFile, TemporaryDirectory, better_mktemp
|
||||
from calibre.utils.config_base import prefs
|
||||
from calibre.utils.date import parse_date
|
||||
from polyglot.builtins import iteritems, itervalues, string_or_bytes
|
||||
@ -115,8 +116,7 @@ class KOBO(USBMS):
|
||||
SUPPORTS_SUB_DIRS = True
|
||||
SUPPORTS_ANNOTATIONS = True
|
||||
|
||||
# "kepubs" do not have an extension. The name looks like a GUID. Using an empty string seems to work.
|
||||
VIRTUAL_BOOK_EXTENSIONS = frozenset(('kobo', ''))
|
||||
VIRTUAL_BOOK_EXTENSIONS = frozenset(('kobo',))
|
||||
|
||||
EXTRA_CUSTOMIZATION_MESSAGE = [
|
||||
_('The Kobo supports several collections including ')+ 'Read, Closed, Im_Reading. ' + _(
|
||||
@ -773,7 +773,7 @@ class KOBO(USBMS):
|
||||
# Supported database version
|
||||
return True
|
||||
|
||||
def get_file(self, path, *args, **kwargs):
|
||||
def get_file(self, path, outfile, end_session=True):
|
||||
tpath = self.munge_path(path)
|
||||
extension = os.path.splitext(tpath)[1]
|
||||
if extension == '.kobo':
|
||||
@ -783,8 +783,20 @@ class KOBO(USBMS):
|
||||
'instead they are rows in the sqlite database. '
|
||||
'Currently they cannot be exported or viewed.'),
|
||||
UserFeedback.WARN)
|
||||
if tpath.lower().endswith(KEPUB_EXT + EPUB_EXT):
|
||||
with TemporaryDirectory() as tdir:
|
||||
outpath = os.path.join(tdir, 'file.epub')
|
||||
from calibre.ebooks.oeb.polish.kepubify import unkepubify_path
|
||||
try:
|
||||
unkepubify_path(path, outpath, allow_overwrite=True)
|
||||
except DRMError:
|
||||
pass
|
||||
else:
|
||||
with open(outpath, 'rb') as src:
|
||||
shutil.copyfile(src, outfile)
|
||||
return
|
||||
|
||||
return USBMS.get_file(self, path, *args, **kwargs)
|
||||
return USBMS.get_file(self, path, outfile, end_session=end_session)
|
||||
|
||||
@classmethod
|
||||
def book_from_path(cls, prefix, lpath, title, authors, mime, date, ContentType, ImageID):
|
||||
@ -1125,17 +1137,23 @@ class KOBO(USBMS):
|
||||
with no file extension. I just hope that decision causes
|
||||
them as much grief as it does me :-)
|
||||
|
||||
This has to make a temporary copy of the book files with a
|
||||
This has to make a temporary copy of the book files with an
|
||||
epub extension to allow calibre's normal processing to
|
||||
deal with the file appropriately
|
||||
'''
|
||||
for idx, path in enumerate(paths):
|
||||
if path.find('kepub') >= 0:
|
||||
with closing(open(path, 'rb')) as r:
|
||||
tf = PersistentTemporaryFile(suffix='.epub')
|
||||
shutil.copyfileobj(r, tf)
|
||||
# tf.write(r.read())
|
||||
paths[idx] = tf.name
|
||||
parts = path.replace(os.sep, '/').split('/')
|
||||
if path.lower().endswith(KEPUB_EXT + EPUB_EXT) or ('kepub' in parts and '.' not in parts[-1]):
|
||||
with PersistentTemporaryFile(suffix=EPUB_EXT) as dest:
|
||||
pass
|
||||
from calibre.ebooks.oeb.polish.kepubify import unkepubify_path
|
||||
try:
|
||||
unkepubify_path(path, dest.name, allow_overwrite=True)
|
||||
except DRMError as e:
|
||||
import traceback
|
||||
paths[idx] = (path, e, traceback.format_exc())
|
||||
else:
|
||||
paths[idx] = dest.name
|
||||
return paths
|
||||
|
||||
@classmethod
|
||||
@ -2332,7 +2350,6 @@ class KOBOTOUCH(KOBO):
|
||||
return result
|
||||
|
||||
def _kepubify(self, path, name, mi, extra_css) -> None:
|
||||
from calibre.ebooks.oeb.polish.errors import DRMError
|
||||
from calibre.ebooks.oeb.polish.kepubify import kepubify_path, make_options
|
||||
debug_print(f'Starting conversion of {mi.title} ({name}) to kepub')
|
||||
opts = make_options(
|
||||
|
@ -28,6 +28,7 @@ from calibre.ebooks.oeb.base import OEB_DOCS, OEB_STYLES, XHTML, XPath, escape_c
|
||||
from calibre.ebooks.oeb.parse_utils import barename, merge_multiple_html_heads_and_bodies
|
||||
from calibre.ebooks.oeb.polish.container import Container, EpubContainer, get_container
|
||||
from calibre.ebooks.oeb.polish.cover import find_cover_image, find_cover_image3, find_cover_page
|
||||
from calibre.ebooks.oeb.polish.errors import DRMError
|
||||
from calibre.ebooks.oeb.polish.parsing import parse
|
||||
from calibre.ebooks.oeb.polish.tts import lang_for_elem
|
||||
from calibre.ebooks.oeb.polish.utils import extract, insert_self_closing
|
||||
@ -516,8 +517,24 @@ def kepubify_path(path, outpath='', max_workers=0, allow_overwrite=False, opts:
|
||||
return outpath
|
||||
|
||||
|
||||
def check_for_kobo_drm(container: Container) -> None:
|
||||
# sadly rights.xml is not definitive as various dedrm tools leave it behind
|
||||
has_rights_xml = container.has_name_and_is_not_empty('rights.xml')
|
||||
if not has_rights_xml:
|
||||
return
|
||||
for name, is_linear in container.spine_names:
|
||||
mt = container.mime_map[name]
|
||||
if mt in OEB_DOCS:
|
||||
with container.open(name, 'rb') as f:
|
||||
raw = f.read(8192)
|
||||
if b'<?xml' not in raw and b'<html' not in raw and KOBO_SPAN_CLASS.encode() not in raw:
|
||||
raise DRMError()
|
||||
break
|
||||
|
||||
|
||||
def unkepubify_path(path, outpath='', max_workers=0, allow_overwrite=False):
|
||||
container = get_container(path, tweak_mode=True, ebook_cls=EpubContainer)
|
||||
check_for_kobo_drm(container)
|
||||
unkepubify_container(container, max_workers)
|
||||
base, ext = os.path.splitext(path)
|
||||
outpath = outpath or base + '.epub'
|
||||
|
Loading…
x
Reference in New Issue
Block a user