diff --git a/cps/tasks/convert.py b/cps/tasks/convert.py
index bba519ac..dbdfae06 100644
--- a/cps/tasks/convert.py
+++ b/cps/tasks/convert.py
@@ -1,349 +1,351 @@
-# -*- coding: utf-8 -*-
-
-# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
-# Copyright (C) 2020 pwr
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-import os
-import re
-from glob import glob
-from shutil import copyfile, copyfileobj
-from markupsafe import escape
-from time import time
-from uuid import uuid4
-
-from sqlalchemy.exc import SQLAlchemyError
-from flask_babel import lazy_gettext as N_
-
-from cps.services.worker import CalibreTask
-from cps import db
-from cps import logger, config
-from cps.subproc_wrapper import process_open
-from flask_babel import gettext as _
-from cps.kobo_sync_status import remove_synced_book
-from cps.ub import init_db_thread
-from cps.file_helper import get_temp_dir
-
-from cps.tasks.mail import TaskEmail
-from cps import gdriveutils, helper
-from cps.constants import SUPPORTED_CALIBRE_BINARIES
-from cps.string_helper import strip_whitespaces
-
-log = logger.create()
-
-current_milli_time = lambda: int(round(time() * 1000))
-
-
-class TaskConvert(CalibreTask):
- def __init__(self, file_path, book_id, task_message, settings, ereader_mail, user=None):
- super(TaskConvert, self).__init__(task_message)
- self.worker_thread = None
- self.file_path = file_path
- self.book_id = book_id
- self.title = ""
- self.settings = settings
- self.ereader_mail = ereader_mail
- self.user = user
-
- self.results = dict()
-
- def run(self, worker_thread):
- self.worker_thread = worker_thread
- if config.config_use_google_drive:
- worker_db = db.CalibreDB(expire_on_commit=False, init=True)
- cur_book = worker_db.get_book(self.book_id)
- self.title = cur_book.title
- data = worker_db.get_book_format(self.book_id, self.settings['old_book_format'])
- df = gdriveutils.getFileFromEbooksFolder(cur_book.path,
- data.name + "." + self.settings['old_book_format'].lower())
- df_cover = gdriveutils.getFileFromEbooksFolder(cur_book.path, "cover.jpg")
- if df:
- datafile_cover = None
- datafile = os.path.join(config.get_book_path(),
- cur_book.path,
- data.name + "." + self.settings['old_book_format'].lower())
- if df_cover:
- datafile_cover = os.path.join(config.get_book_path(),
- cur_book.path, "cover.jpg")
- if not os.path.exists(os.path.join(config.get_book_path(), cur_book.path)):
- os.makedirs(os.path.join(config.get_book_path(), cur_book.path))
- df.GetContentFile(datafile)
- if df_cover:
- df_cover.GetContentFile(datafile_cover)
- worker_db.session.close()
- else:
- # ToDo Include cover in error handling
- error_message = _("%(format)s not found on Google Drive: %(fn)s",
- format=self.settings['old_book_format'],
- fn=data.name + "." + self.settings['old_book_format'].lower())
- worker_db.session.close()
- return self._handleError(error_message)
-
- filename = self._convert_ebook_format()
- if config.config_use_google_drive:
- os.remove(self.file_path + '.' + self.settings['old_book_format'].lower())
- if df_cover:
- os.remove(os.path.join(config.config_calibre_dir, cur_book.path, "cover.jpg"))
-
- if filename:
- if config.config_use_google_drive:
- # Upload files to gdrive
- gdriveutils.updateGdriveCalibreFromLocal()
- self._handleSuccess()
- if self.ereader_mail:
- # if we're sending to E-Reader after converting, create a one-off task and run it immediately
- # todo: figure out how to incorporate this into the progress
- try:
- EmailText = N_(u"%(book)s send to E-Reader", book=escape(self.title))
- for email in self.ereader_mail.split(','):
- email = strip_whitespaces(email)
- worker_thread.add(self.user, TaskEmail(self.settings['subject'],
- self.results["path"],
- filename,
- self.settings,
- email,
- EmailText,
- self.settings['body'],
- id=self.book_id,
- internal=True)
- )
- except Exception as ex:
- return self._handleError(str(ex))
-
- def _convert_ebook_format(self):
- error_message = None
- local_db = db.CalibreDB(expire_on_commit=False, init=True)
- file_path = self.file_path
- book_id = self.book_id
- format_old_ext = '.' + self.settings['old_book_format'].lower()
- format_new_ext = '.' + self.settings['new_book_format'].lower()
-
- # check to see if destination format already exists - or if book is in database
- # if it does - mark the conversion task as complete and return a success
- # this will allow to send to E-Reader workflow to continue to work
- if os.path.isfile(file_path + format_new_ext) or\
- local_db.get_book_format(self.book_id, self.settings['new_book_format']):
- log.info("Book id %d already converted to %s", book_id, format_new_ext)
- cur_book = local_db.get_book(book_id)
- self.title = cur_book.title
- self.results['path'] = cur_book.path
- self.results['title'] = self.title
- new_format = local_db.session.query(db.Data).filter(db.Data.book == book_id)\
- .filter(db.Data.format == self.settings['new_book_format'].upper()).one_or_none()
- if not new_format:
- new_format = db.Data(name=os.path.basename(file_path),
- book_format=self.settings['new_book_format'].upper(),
- book=book_id, uncompressed_size=os.path.getsize(file_path + format_new_ext))
- try:
- local_db.session.merge(new_format)
- local_db.session.commit()
- except SQLAlchemyError as e:
- local_db.session.rollback()
- log.error("Database error: %s", e)
- local_db.session.close()
- self._handleError(N_("Oops! Database Error: %(error)s.", error=e))
- return
- self._handleSuccess()
- local_db.session.close()
- return os.path.basename(file_path + format_new_ext)
- else:
- log.info("Book id %d - target format of %s does not exist. Moving forward with convert.",
- book_id,
- format_new_ext)
-
- if config.config_kepubifypath and format_old_ext == '.epub' and format_new_ext == '.kepub':
- check, error_message = self._convert_kepubify(file_path,
- format_old_ext,
- format_new_ext)
- else:
- # check if calibre converter-executable is existing
- if not os.path.exists(config.config_converterpath):
- self._handleError(N_("Calibre ebook-convert %(tool)s not found", tool=config.config_converterpath))
- return
- has_cover = local_db.get_book(book_id).has_cover
- check, error_message = self._convert_calibre(file_path, format_old_ext, format_new_ext, has_cover)
-
- if check == 0:
- cur_book = local_db.get_book(book_id)
- if os.path.isfile(file_path + format_new_ext):
- new_format = local_db.session.query(db.Data).filter(db.Data.book == book_id) \
- .filter(db.Data.format == self.settings['new_book_format'].upper()).one_or_none()
- if not new_format:
- new_format = db.Data(name=cur_book.data[0].name,
- book_format=self.settings['new_book_format'].upper(),
- book=book_id, uncompressed_size=os.path.getsize(file_path + format_new_ext))
- try:
- local_db.session.merge(new_format)
- local_db.session.commit()
- if self.settings['new_book_format'].upper() in ['KEPUB', 'EPUB', 'EPUB3']:
- ub_session = init_db_thread()
- remove_synced_book(book_id, True, ub_session)
- ub_session.close()
- except SQLAlchemyError as e:
- local_db.session.rollback()
- log.error("Database error: %s", e)
- local_db.session.close()
- self._handleError(error_message)
- return
- self.results['path'] = cur_book.path
- self.title = cur_book.title
- self.results['title'] = self.title
- if not config.config_use_google_drive:
- self._handleSuccess()
- return os.path.basename(file_path + format_new_ext)
- else:
- error_message = N_('%(format)s format not found on disk', format=format_new_ext.upper())
- local_db.session.close()
- log.info("ebook converter failed with error while converting book")
- if not error_message:
- error_message = N_('Ebook converter failed with unknown error')
- else:
- log.error(error_message)
- self._handleError(error_message)
- return
-
- def _convert_kepubify(self, file_path, format_old_ext, format_new_ext):
- if config.config_embed_metadata and config.config_binariesdir:
- tmp_dir, temp_file_name = helper.do_calibre_export(self.book_id, format_old_ext[1:])
- filename = os.path.join(tmp_dir, temp_file_name + format_old_ext)
- temp_file_path = tmp_dir
- else:
- filename = file_path + format_old_ext
- temp_file_path = os.path.dirname(file_path)
- quotes = [1, 3]
- command = [config.config_kepubifypath, filename, '-o', temp_file_path, '-i']
- try:
- p = process_open(command, quotes)
- except OSError as e:
- return 1, N_("Kepubify-converter failed: %(error)s", error=e)
- self.progress = 0.01
- while True:
- nextline = p.stdout.readlines()
- nextline = [x.strip('\n') for x in nextline if x != '\n']
- for line in nextline:
- log.debug(line)
- if p.poll() is not None:
- break
-
- # process returncode
- check = p.returncode
-
- # move file
- if check == 0:
- converted_file = glob(os.path.splitext(filename)[0] + "*.kepub.epub")
- if len(converted_file) == 1:
- copyfile(converted_file[0], (file_path + format_new_ext))
- os.unlink(converted_file[0])
- else:
- return 1, N_("Converted file not found or more than one file in folder %(folder)s",
- folder=os.path.dirname(file_path))
- return check, None
-
- def _convert_calibre(self, file_path, format_old_ext, format_new_ext, has_cover):
- path_tmp_opf = None
- try:
- # path_tmp_opf = self._embed_metadata()
- if config.config_embed_metadata:
- quotes = [5]
- tmp_dir = get_temp_dir()
- calibredb_binarypath = os.path.join(config.config_binariesdir, SUPPORTED_CALIBRE_BINARIES["calibredb"])
- my_env = os.environ.copy()
- if config.config_calibre_split:
- my_env['CALIBRE_OVERRIDE_DATABASE_PATH'] = os.path.join(config.config_calibre_dir, "metadata.db")
- library_path = config.config_calibre_split_dir
- else:
- library_path = config.config_calibre_dir
-
- opf_command = [calibredb_binarypath, 'show_metadata', '--as-opf', str(self.book_id),
- '--with-library', library_path]
- p = process_open(opf_command, quotes, my_env)
- p.wait()
- check = p.returncode
- calibre_traceback = p.stderr.readlines()
- if check == 0:
- path_tmp_opf = os.path.join(tmp_dir, "metadata_" + str(uuid4()) + ".opf")
- with open(path_tmp_opf, 'w') as fd:
- copyfileobj(p.stdout, fd)
- else:
- error_message = ""
- for ele in calibre_traceback:
- if not ele.startswith('Traceback') and not ele.startswith(' File'):
- error_message = N_("Calibre failed with error: %(error)s", error=ele)
- return check, error_message
- quotes = [1, 2]
- quotes_index = 3
- command = [config.config_converterpath, (file_path + format_old_ext),
- (file_path + format_new_ext)]
- if config.config_embed_metadata:
- quotes.append([4])
- quotes_index = 5
- command.extend(['--from-opf', path_tmp_opf])
- if has_cover:
- quotes.append([6])
- command.extend(['--cover', os.path.join(os.path.dirname(file_path), 'cover.jpg')])
- quotes_index = 7
- if config.config_calibre:
- parameters = re.findall(r"(--[\w-]+)(?:(\s(?:(\".+\")|(?:.+?)))(?:\s|$))?",
- config.config_calibre, re.IGNORECASE | re.UNICODE)
- if parameters:
- for param in parameters:
- command.append(strip_whitespaces(param[0]))
- quotes_index += 1
- if param[1] != "":
- parsed = strip_whitespaces(param[1]).strip("\"")
- command.append(parsed)
- quotes.append(quotes_index)
- quotes_index += 1
- p = process_open(command, quotes, newlines=False)
- except OSError as e:
- return 1, N_("Ebook-converter failed: %(error)s", error=e)
-
- while p.poll() is None:
- nextline = p.stdout.readline()
- if isinstance(nextline, bytes):
- nextline = nextline.decode('utf-8', errors="ignore").strip('\r\n')
- if nextline:
- log.debug(nextline)
- # parse progress string from calibre-converter
- progress = re.search(r"(\d+)%\s.*", nextline)
- if progress:
- self.progress = int(progress.group(1)) / 100
- if config.config_use_google_drive:
- self.progress *= 0.9
-
- # process returncode
- check = p.returncode
- calibre_traceback = p.stderr.readlines()
- error_message = ""
- for ele in calibre_traceback:
- ele = ele.decode('utf-8', errors="ignore").strip('\n')
- log.debug(ele)
- if not ele.startswith('Traceback') and not ele.startswith(' File'):
- error_message = N_("Calibre failed with error: %(error)s", error=ele)
- return check, error_message
-
- @property
- def name(self):
- return N_("Convert")
-
- def __str__(self):
- if self.ereader_mail:
- return "Convert Book {} and mail it to {}".format(self.book_id, self.ereader_mail)
- else:
- return "Convert Book {}".format(self.book_id)
-
- @property
- def is_cancellable(self):
- return False
+# -*- coding: utf-8 -*-
+
+# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
+# Copyright (C) 2020 pwr
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import os
+import re
+from glob import glob
+from shutil import copyfile, copyfileobj
+from markupsafe import escape
+from time import time
+from uuid import uuid4
+
+from sqlalchemy.exc import SQLAlchemyError
+from flask_babel import lazy_gettext as N_
+
+from cps.services.worker import CalibreTask
+from cps import db
+from cps import logger, config
+from cps.subproc_wrapper import process_open
+from flask_babel import gettext as _
+from cps.kobo_sync_status import remove_synced_book
+from cps.ub import init_db_thread
+from cps.file_helper import get_temp_dir
+
+from cps.tasks.mail import TaskEmail
+from cps import gdriveutils, helper
+from cps.constants import SUPPORTED_CALIBRE_BINARIES
+from cps.string_helper import strip_whitespaces
+
+log = logger.create()
+
+current_milli_time = lambda: int(round(time() * 1000))
+
+
+class TaskConvert(CalibreTask):
+ def __init__(self, file_path, book_id, task_message, settings, ereader_mail, user=None):
+ super(TaskConvert, self).__init__(task_message)
+ self.worker_thread = None
+ self.file_path = file_path
+ self.book_id = book_id
+ self.title = ""
+ self.settings = settings
+ self.ereader_mail = ereader_mail
+ self.user = user
+
+ self.results = dict()
+
+ def run(self, worker_thread):
+ self.worker_thread = worker_thread
+ if config.config_use_google_drive:
+ worker_db = db.CalibreDB(expire_on_commit=False, init=True)
+ cur_book = worker_db.get_book(self.book_id)
+ self.title = cur_book.title
+ data = worker_db.get_book_format(self.book_id, self.settings['old_book_format'])
+ df = gdriveutils.getFileFromEbooksFolder(cur_book.path,
+ data.name + "." + self.settings['old_book_format'].lower())
+ df_cover = gdriveutils.getFileFromEbooksFolder(cur_book.path, "cover.jpg")
+ if df:
+ datafile_cover = None
+ datafile = os.path.join(config.get_book_path(),
+ cur_book.path,
+ data.name + "." + self.settings['old_book_format'].lower())
+ if df_cover:
+ datafile_cover = os.path.join(config.get_book_path(),
+ cur_book.path, "cover.jpg")
+ if not os.path.exists(os.path.join(config.get_book_path(), cur_book.path)):
+ os.makedirs(os.path.join(config.get_book_path(), cur_book.path))
+ df.GetContentFile(datafile)
+ if df_cover:
+ df_cover.GetContentFile(datafile_cover)
+ worker_db.session.close()
+ else:
+ # ToDo Include cover in error handling
+ error_message = _("%(format)s not found on Google Drive: %(fn)s",
+ format=self.settings['old_book_format'],
+ fn=data.name + "." + self.settings['old_book_format'].lower())
+ worker_db.session.close()
+ return self._handleError(error_message)
+
+ filename = self._convert_ebook_format()
+ if config.config_use_google_drive:
+ os.remove(self.file_path + '.' + self.settings['old_book_format'].lower())
+ if df_cover:
+ os.remove(os.path.join(config.config_calibre_dir, cur_book.path, "cover.jpg"))
+
+ if filename:
+ if config.config_use_google_drive:
+ # Upload files to gdrive
+ gdriveutils.updateGdriveCalibreFromLocal()
+ self._handleSuccess()
+ if self.ereader_mail:
+ # if we're sending to E-Reader after converting, create a one-off task and run it immediately
+ # todo: figure out how to incorporate this into the progress
+ try:
+ EmailText = N_(u"%(book)s send to E-Reader", book=escape(self.title))
+ for email in self.ereader_mail.split(','):
+ email = strip_whitespaces(email)
+ worker_thread.add(self.user, TaskEmail(self.settings['subject'],
+ self.results["path"],
+ filename,
+ self.settings,
+ email,
+ EmailText,
+ self.settings['body'],
+ id=self.book_id,
+ internal=True)
+ )
+ except Exception as ex:
+ return self._handleError(str(ex))
+
+ def _convert_ebook_format(self):
+ error_message = None
+ local_db = db.CalibreDB(expire_on_commit=False, init=True)
+ file_path = self.file_path
+ book_id = self.book_id
+ format_old_ext = '.' + self.settings['old_book_format'].lower()
+ format_new_ext = '.' + self.settings['new_book_format'].lower()
+
+ # check to see if destination format already exists - or if book is in database
+ # if it does - mark the conversion task as complete and return a success
+ # this will allow to send to E-Reader workflow to continue to work
+ if os.path.isfile(file_path + format_new_ext) or\
+ local_db.get_book_format(self.book_id, self.settings['new_book_format']):
+ log.info("Book id %d already converted to %s", book_id, format_new_ext)
+ cur_book = local_db.get_book(book_id)
+ self.title = cur_book.title
+ self.results['path'] = cur_book.path
+ self.results['title'] = self.title
+ new_format = local_db.session.query(db.Data).filter(db.Data.book == book_id)\
+ .filter(db.Data.format == self.settings['new_book_format'].upper()).one_or_none()
+ if not new_format:
+ new_format = db.Data(name=os.path.basename(file_path),
+ book_format=self.settings['new_book_format'].upper(),
+ book=book_id, uncompressed_size=os.path.getsize(file_path + format_new_ext))
+ try:
+ local_db.session.merge(new_format)
+ local_db.session.commit()
+ except SQLAlchemyError as e:
+ local_db.session.rollback()
+ log.error("Database error: %s", e)
+ local_db.session.close()
+ self._handleError(N_("Oops! Database Error: %(error)s.", error=e))
+ return
+ self._handleSuccess()
+ local_db.session.close()
+ return os.path.basename(file_path + format_new_ext)
+ else:
+ log.info("Book id %d - target format of %s does not exist. Moving forward with convert.",
+ book_id,
+ format_new_ext)
+
+ if config.config_kepubifypath and format_old_ext == '.epub' and format_new_ext == '.kepub':
+ check, error_message = self._convert_kepubify(file_path,
+ format_old_ext,
+ format_new_ext)
+ else:
+ # check if calibre converter-executable is existing
+ if not os.path.exists(config.config_converterpath):
+ self._handleError(N_("Calibre ebook-convert %(tool)s not found", tool=config.config_converterpath))
+ return
+ has_cover = local_db.get_book(book_id).has_cover
+ check, error_message = self._convert_calibre(file_path, format_old_ext, format_new_ext, has_cover)
+
+ if check == 0:
+ cur_book = local_db.get_book(book_id)
+ if os.path.isfile(file_path + format_new_ext):
+ new_format = local_db.session.query(db.Data).filter(db.Data.book == book_id) \
+ .filter(db.Data.format == self.settings['new_book_format'].upper()).one_or_none()
+ if not new_format:
+ new_format = db.Data(name=cur_book.data[0].name,
+ book_format=self.settings['new_book_format'].upper(),
+ book=book_id, uncompressed_size=os.path.getsize(file_path + format_new_ext))
+ try:
+ local_db.session.merge(new_format)
+ local_db.session.commit()
+ if self.settings['new_book_format'].upper() in ['KEPUB', 'EPUB', 'EPUB3']:
+ ub_session = init_db_thread()
+ remove_synced_book(book_id, True, ub_session)
+ ub_session.close()
+ except SQLAlchemyError as e:
+ local_db.session.rollback()
+ log.error("Database error: %s", e)
+ local_db.session.close()
+ self._handleError(error_message)
+ return
+ self.results['path'] = cur_book.path
+ self.title = cur_book.title
+ self.results['title'] = self.title
+ if not config.config_use_google_drive:
+ self._handleSuccess()
+ return os.path.basename(file_path + format_new_ext)
+ else:
+ error_message = N_('%(format)s format not found on disk', format=format_new_ext.upper())
+ local_db.session.close()
+ log.info("ebook converter failed with error while converting book")
+ if not error_message:
+ error_message = N_('Ebook converter failed with unknown error')
+ else:
+ log.error(error_message)
+ self._handleError(error_message)
+ return
+
+ def _convert_kepubify(self, file_path, format_old_ext, format_new_ext):
+ if config.config_embed_metadata and config.config_binariesdir:
+ tmp_dir, temp_file_name = helper.do_calibre_export(self.book_id, format_old_ext[1:])
+ filename = os.path.join(tmp_dir, temp_file_name + format_old_ext)
+ temp_file_path = tmp_dir
+ else:
+ filename = file_path + format_old_ext
+ temp_file_path = os.path.dirname(file_path)
+ quotes = [1, 3]
+ command = [config.config_kepubifypath, filename, '-o', temp_file_path, '-i']
+ try:
+ p = process_open(command, quotes)
+ except OSError as e:
+ return 1, N_("Kepubify-converter failed: %(error)s", error=e)
+ self.progress = 0.01
+ while True:
+ nextline = p.stdout.readlines()
+ nextline = [x.strip('\n') for x in nextline if x != '\n']
+ for line in nextline:
+ log.debug(line)
+ if p.poll() is not None:
+ break
+
+ # process returncode
+ check = p.returncode
+
+ # move file
+ if check == 0:
+ converted_file = glob(os.path.splitext(filename)[0] + "*.kepub.epub")
+ if len(converted_file) == 1:
+ copyfile(converted_file[0], (file_path + format_new_ext))
+ os.unlink(converted_file[0])
+ else:
+ return 1, N_("Converted file not found or more than one file in folder %(folder)s",
+ folder=os.path.dirname(file_path))
+ return check, None
+
+ def _convert_calibre(self, file_path, format_old_ext, format_new_ext, has_cover):
+ path_tmp_opf = None
+ try:
+ # path_tmp_opf = self._embed_metadata()
+ if config.config_embed_metadata:
+ quotes = [5]
+ tmp_dir = get_temp_dir()
+ calibredb_binarypath = os.path.join(config.config_binariesdir, SUPPORTED_CALIBRE_BINARIES["calibredb"])
+ my_env = os.environ.copy()
+ if config.config_calibre_split:
+ my_env['CALIBRE_OVERRIDE_DATABASE_PATH'] = os.path.join(config.config_calibre_dir, "metadata.db")
+ library_path = config.config_calibre_split_dir
+ else:
+ library_path = config.config_calibre_dir
+
+ opf_command = [calibredb_binarypath, 'show_metadata', '--as-opf', str(self.book_id),
+ '--with-library', library_path]
+ p = process_open(opf_command, quotes, my_env, newlines=False)
+ lines = list()
+ while p.poll() is None:
+ lines.append(p.stdout.readline())
+ check = p.returncode
+ calibre_traceback = p.stderr.readlines()
+ if check == 0:
+ path_tmp_opf = os.path.join(tmp_dir, "metadata_" + str(uuid4()) + ".opf")
+ with open(path_tmp_opf, 'wb') as fd:
+ fd.write(b''.join(lines))
+ else:
+ error_message = ""
+ for ele in calibre_traceback:
+ if not ele.startswith('Traceback') and not ele.startswith(' File'):
+ error_message = N_("Calibre failed with error: %(error)s", error=ele)
+ return check, error_message
+ quotes = [1, 2]
+ quotes_index = 3
+ command = [config.config_converterpath, (file_path + format_old_ext),
+ (file_path + format_new_ext)]
+ if config.config_embed_metadata:
+ quotes.append(4)
+ quotes_index = 5
+ command.extend(['--from-opf', path_tmp_opf])
+ if has_cover:
+ quotes.append(6)
+ command.extend(['--cover', os.path.join(os.path.dirname(file_path), 'cover.jpg')])
+ quotes_index = 7
+ if config.config_calibre:
+ parameters = re.findall(r"(--[\w-]+)(?:(\s(?:(\".+\")|(?:.+?)))(?:\s|$))?",
+ config.config_calibre, re.IGNORECASE | re.UNICODE)
+ if parameters:
+ for param in parameters:
+ command.append(strip_whitespaces(param[0]))
+ quotes_index += 1
+ if param[1] != "":
+ parsed = strip_whitespaces(param[1]).strip("\"")
+ command.append(parsed)
+ quotes.append(quotes_index)
+ quotes_index += 1
+ p = process_open(command, quotes, newlines=False)
+ except OSError as e:
+ return 1, N_("Ebook-converter failed: %(error)s", error=e)
+
+ while p.poll() is None:
+ nextline = p.stdout.readline()
+ if isinstance(nextline, bytes):
+ nextline = nextline.decode('utf-8', errors="ignore").strip('\r\n')
+ if nextline:
+ log.debug(nextline)
+ # parse progress string from calibre-converter
+ progress = re.search(r"(\d+)%\s.*", nextline)
+ if progress:
+ self.progress = int(progress.group(1)) / 100
+ if config.config_use_google_drive:
+ self.progress *= 0.9
+
+ # process returncode
+ check = p.returncode
+ calibre_traceback = p.stderr.readlines()
+ error_message = ""
+ for ele in calibre_traceback:
+ ele = ele.decode('utf-8', errors="ignore").strip('\n')
+ log.debug(ele)
+ if not ele.startswith('Traceback') and not ele.startswith(' File'):
+ error_message = N_("Calibre failed with error: %(error)s", error=ele)
+ return check, error_message
+
+ @property
+ def name(self):
+ return N_("Convert")
+
+ def __str__(self):
+ if self.ereader_mail:
+ return "Convert Book {} and mail it to {}".format(self.book_id, self.ereader_mail)
+ else:
+ return "Convert Book {}".format(self.book_id)
+
+ @property
+ def is_cancellable(self):
+ return False