From 9bcbe523d7660c4d14bf2742ee998212cbe230d6 Mon Sep 17 00:00:00 2001 From: Thore Schillmann Date: Fri, 22 Jul 2022 08:58:28 +0000 Subject: [PATCH] (draft) metadata embedding when sending to device --- cps/constants.py | 2 +- cps/helper.py | 13 ++++++++++++- cps/tasks/convert.py | 10 ++++++++++ cps/tasks/mail.py | 27 ++++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/cps/constants.py b/cps/constants.py index b613d0aa..d8b05cb3 100644 --- a/cps/constants.py +++ b/cps/constants.py @@ -154,7 +154,7 @@ EXTENSIONS_UPLOAD = {'txt', 'pdf', 'epub', 'kepub', 'mobi', 'azw', 'azw3', 'cbr' _extension = "" if sys.platform == "win32": _extension = ".exe" -SUPPORTED_CALIBRE_BINARIES = {binary:binary + _extension for binary in ["ebook-convert", "calibredb"]} +SUPPORTED_CALIBRE_BINARIES = {binary:binary + _extension for binary in ["ebook-convert", "calibredb", "ebook-meta"]} def has_flag(value, bit_flag): diff --git a/cps/helper.py b/cps/helper.py index a16245fa..80056244 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -54,7 +54,7 @@ from .tasks.convert import TaskConvert from . import logger, config, db, ub, fs from . import gdriveutils as gd from .constants import STATIC_DIR as _STATIC_DIR, CACHE_TYPE_THUMBNAILS, THUMBNAIL_TYPE_COVER, THUMBNAIL_TYPE_SERIES, SUPPORTED_CALIBRE_BINARIES -from .subproc_wrapper import process_wait +from .subproc_wrapper import process_wait, process_open from .services.worker import WorkerThread from .tasks.mail import TaskEmail from .tasks.thumbnail import TaskClearCoverThumbnailCache, TaskGenerateCoverThumbnails @@ -213,6 +213,17 @@ def send_mail(book_id, book_format, convert, kindle_mail, calibrepath, user_id): # returns None if success, otherwise errormessage return convert_book_format(book_id, calibrepath, u'azw3', book_format.lower(), user_id, kindle_mail) + # ToDo: Delete when OPF creation has been implemented + if config.config_binariesdir: + quotes = [3, 5] + calibredb_binarypath = os.path.join(config.config_binariesdir, SUPPORTED_CALIBRE_BINARIES["calibredb"]) + opf_command = [calibredb_binarypath, 'show_metadata', '--as-opf', str(book_id), '--with-library', config.config_calibre_dir] + p = process_open(opf_command, quotes) + p.wait() + path_opf = os.path.join(config.config_calibre_dir, book.path, "metadata.opf") + with open(path_opf, 'w') as fd: + shutil.copyfileobj(p.stdout, fd) + for entry in iter(book.data): if entry.format.upper() == book_format.upper(): converted_file_name = entry.name + '.' + book_format.lower() diff --git a/cps/tasks/convert.py b/cps/tasks/convert.py index 79d7ddbd..23af302a 100644 --- a/cps/tasks/convert.py +++ b/cps/tasks/convert.py @@ -93,6 +93,16 @@ class TaskConvert(CalibreTask): # todo: figure out how to incorporate this into the progress try: EmailText = N_(u"%(book)s send to Kindle", book=escape(self.title)) + # ToDo: Delete when OPF creation has been implemented + if config.config_binariesdir: + quotes = [3, 5] + calibredb_binarypath = os.path.join(config.config_binariesdir, SUPPORTED_CALIBRE_BINARIES["calibredb"]) + opf_command = [calibredb_binarypath, 'show_metadata', '--as-opf', str(self.book_id), '--with-library', config.config_calibre_dir] + p = process_open(opf_command, quotes) + p.wait() + path_opf = os.path.join(config.config_calibre_dir, cur_book.path, "metadata.opf") + with open(path_opf, 'w') as fd: + copyfileobj(p.stdout, fd) worker_thread.add(self.user, TaskEmail(self.settings['subject'], self.results["path"], filename, diff --git a/cps/tasks/mail.py b/cps/tasks/mail.py index be240c79..6c94faee 100755 --- a/cps/tasks/mail.py +++ b/cps/tasks/mail.py @@ -20,6 +20,7 @@ import os import smtplib import threading import socket +from shutil import copy import mimetypes from io import StringIO @@ -32,6 +33,8 @@ from email.utils import formatdate from cps.services.worker import CalibreTask from cps.services import gmail from cps import logger, config +from cps.subproc_wrapper import process_open +from cps.constants import SUPPORTED_CALIBRE_BINARIES from cps import gdriveutils import uuid @@ -245,15 +248,23 @@ class TaskEmail(CalibreTask): df.GetContentFile(datafile) else: return None + if config.config_binariesdir: + datafile = cls._embed_metadata(calibre_path, book_path, filename, datafile) + os.remove(os.path.join(calibre_path, book_path, filename)) file_ = open(datafile, 'rb') data = file_.read() file_.close() os.remove(datafile) else: + datafile = os.path.join(calibre_path, book_path, filename) try: - file_ = open(os.path.join(calibre_path, book_path, filename), 'rb') + if config.config_binariesdir: + datafile = cls._embed_metadata(calibre_path, book_path, filename, datafile) + file_ = open(datafile, 'rb') data = file_.read() file_.close() + if config.config_binariesdir: + os.remove(datafile) except IOError as e: log.error_or_exception(e, stacklevel=3) log.error(u'The requested file could not be read. Maybe wrong permissions?') @@ -270,3 +281,17 @@ class TaskEmail(CalibreTask): def __str__(self): return "E-mail {}, {}".format(self.name, self.subject) + + def _embed_metadata(self, calibre_path, book_path, filename, datafile): + datafile_tmp = os.path.join(calibre_path, book_path, "tmp_" + filename) + path_opf = os.path.join(calibre_path, book_path, "metadata.opf") + copy(datafile, datafile_tmp) + + calibredb_binarypath = os.path.join(config.config_binariesdir, SUPPORTED_CALIBRE_BINARIES["ebook-meta"]) + opf_command = [calibredb_binarypath, datafile_tmp, "--from-opf", path_opf] + p = process_open(opf_command) + _, err = p.communicate() + if err: + # ToDo: Improve error handling + log.error('Metadata embedder encountered an error: %s', err) + return datafile_tmp