Ejemplo n.º 1
0
    def _convert_kepubify(self, file_path, format_old_ext, format_new_ext):
        quotes = [1, 3]
        command = [
            config.config_kepubifypath, (file_path + format_old_ext), '-o',
            os.path.dirname(file_path)
        ]
        try:
            p = process_open(command, quotes)
        except OSError as e:
            return 1, N_(u"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

        # ToD Handle
        # process returncode
        check = p.returncode

        # move file
        if check == 0:
            converted_file = glob(
                os.path.join(os.path.dirname(file_path), "*.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_(
                    u"Converted file not found or more than one file in folder %(folder)s",
                    folder=os.path.dirname(file_path))
        return check, None
Ejemplo n.º 2
0
    def _convert_calibre(self, file_path, format_old_ext, format_new_ext):
        try:
            # Linux py2.7 encode as list without quotes no empty element for parameters
            # linux py3.x no encode and as list without quotes no empty element for parameters
            # windows py2.7 encode as string with quotes empty element for parameters is okay
            # windows py 3.x no encode and as string with quotes empty element for parameters is okay
            # separate handling for windows and linux
            quotes = [1, 2]
            command = [
                config.config_converterpath, (file_path + format_old_ext),
                (file_path + format_new_ext)
            ]
            quotes_index = 3
            if config.config_calibre:
                parameters = config.config_calibre.split(" ")
                for param in parameters:
                    command.append(param)
                    quotes.append(quotes_index)
                    quotes_index += 1

            p = process_open(command, quotes, newlines=False)
        except OSError as e:
            return 1, N_(u"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
Ejemplo n.º 3
0
def send_mail(book_id, book_format, convert, ereader_mail, calibrepath,
              user_id):
    """Send email with attachments"""
    book = calibre_db.get_book(book_id)

    if convert == 1:
        # returns None if success, otherwise errormessage
        return convert_book_format(book_id, calibrepath, u'epub',
                                   book_format.lower(), user_id, ereader_mail)
    if convert == 2:
        # returns None if success, otherwise errormessage
        return convert_book_format(book_id, calibrepath, u'azw3',
                                   book_format.lower(), user_id, ereader_mail)

    for entry in iter(book.data):
        if entry.format.upper() == book_format.upper():
            converted_file_name = entry.name + '.' + book_format.lower()
            link = '<a href="{}">{}</a>'.format(
                url_for('web.show_book', book_id=book_id), escape(book.title))
            email_text = N_(u"%(book)s send to E-Reader", book=link)
            WorkerThread.add(
                user_id,
                TaskEmail(_(u"Send to E-Reader"),
                          book.path, converted_file_name,
                          config.get_mail_settings(), ereader_mail, email_text,
                          _(u'This e-mail has been sent via Calibre-Web.')))
            return
    return _(u"The requested file could not be read. Maybe wrong permissions?")
Ejemplo n.º 4
0
def send_test_mail(ereader_mail, user_name):
    WorkerThread.add(
        user_name,
        TaskEmail(_(u'Calibre-Web test e-mail'), None, None,
                  config.get_mail_settings(), ereader_mail, N_(u"Test e-mail"),
                  _(u'This e-mail has been sent via Calibre-Web.')))
    return
Ejemplo n.º 5
0
    def run(self, worker_thread):
        if self.calibre_db.session and use_IM and self.stat != STAT_CANCELLED and self.stat != STAT_ENDED:
            self.message = 'Scanning Series'
            all_series = self.get_series_with_four_plus_books()
            count = len(all_series)

            total_generated = 0
            for i, series in enumerate(all_series):
                generated = 0
                series_thumbnails = self.get_series_thumbnails(series.id)
                series_books = self.get_series_books(series.id)

                # Generate new thumbnails for missing covers
                resolutions = list(
                    map(lambda t: t.resolution, series_thumbnails))
                missing_resolutions = list(
                    set(self.resolutions).difference(resolutions))
                for resolution in missing_resolutions:
                    generated += 1
                    self.create_series_thumbnail(series, series_books,
                                                 resolution)

                # Replace outdated or missing thumbnails
                for thumbnail in series_thumbnails:
                    if any(book.last_modified > thumbnail.generated_at
                           for book in series_books):
                        generated += 1
                        self.update_series_thumbnail(series_books, thumbnail)

                    elif not self.cache.get_cache_file_exists(
                            thumbnail.filename,
                            constants.CACHE_TYPE_THUMBNAILS):
                        generated += 1
                        self.update_series_thumbnail(series_books, thumbnail)

                # Increment the progress
                self.progress = (1.0 / count) * i

                if generated > 0:
                    total_generated += generated
                    self.message = N_('Generated {0} series thumbnails'
                                      ).format(total_generated)

                # Check if job has been cancelled or ended
                if self.stat == STAT_CANCELLED:
                    self.log.info(
                        f'GenerateSeriesThumbnails task has been cancelled.')
                    return

                if self.stat == STAT_ENDED:
                    self.log.info(
                        f'GenerateSeriesThumbnails task has been ended.')
                    return

            if total_generated == 0:
                self.self_cleanup = True

        self._handleSuccess()
        self.app_db_session.remove()
Ejemplo n.º 6
0
    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())
            if df:
                datafile = os.path.join(
                    config.config_calibre_dir, cur_book.path, data.name +
                    u"." + self.settings['old_book_format'].lower())
                if not os.path.exists(
                        os.path.join(config.config_calibre_dir,
                                     cur_book.path)):
                    os.makedirs(
                        os.path.join(config.config_calibre_dir, cur_book.path))
                df.GetContentFile(datafile)
                worker_db.session.close()
            else:
                error_message = _(
                    u"%(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 error_message

        filename = self._convert_ebook_format()
        if config.config_use_google_drive:
            os.remove(self.file_path + u'.' +
                      self.settings['old_book_format'].lower())

        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))
                    worker_thread.add(
                        self.user,
                        TaskEmail(self.settings['subject'],
                                  self.results["path"],
                                  filename,
                                  self.settings,
                                  self.ereader_mail,
                                  EmailText,
                                  self.settings['body'],
                                  internal=True))
                except Exception as ex:
                    return self._handleError(str(ex))
Ejemplo n.º 7
0
 def __init__(self,
              book_id,
              task_message=N_('Clearing cover thumbnail cache')):
     super(TaskClearCoverThumbnailCache, self).__init__(task_message)
     self.log = logger.create()
     self.book_id = book_id
     self.app_db_session = ub.get_new_session_instance()
     self.cache = fs.FileSystem()
Ejemplo n.º 8
0
def send_registration_mail(e_mail, user_name, default_password, resend=False):
    txt = "Hello %s!\r\n" % user_name
    if not resend:
        txt += "Your new account at Calibre-Web has been created. Thanks for joining us!\r\n"
    txt += "Please log in to your account using the following informations:\r\n"
    txt += "User name: %s\r\n" % user_name
    txt += "Password: %s\r\n" % default_password
    txt += "Don't forget to change your password after first login.\r\n"
    txt += "Sincerely\r\n\r\n"
    txt += "Your Calibre-Web team"
    WorkerThread.add(None, TaskEmail(
        subject=_(u'Get Started with Calibre-Web'),
        filepath=None,
        attachment=None,
        settings=config.get_mail_settings(),
        recipient=e_mail,
        task_message=N_(u"Registration e-mail for user: %(name)s", name=user_name),
        text=txt
    ))
    return
Ejemplo n.º 9
0
    def run(self, worker_thread):
        if use_IM and self.stat != STAT_CANCELLED and self.stat != STAT_ENDED:
            self.message = 'Scanning Books'
            books_with_covers = self.get_books_with_covers(self.book_id)
            count = len(books_with_covers)

            total_generated = 0
            for i, book in enumerate(books_with_covers):

                # Generate new thumbnails for missing covers
                generated = self.create_book_cover_thumbnails(book)

                # Increment the progress
                self.progress = (1.0 / count) * i

                if generated > 0:
                    total_generated += generated
                    self.message = N_(u'Generated %(count)s cover thumbnails',
                                      count=total_generated)

                # Check if job has been cancelled or ended
                if self.stat == STAT_CANCELLED:
                    self.log.info(
                        f'GenerateCoverThumbnails task has been cancelled.')
                    return

                if self.stat == STAT_ENDED:
                    self.log.info(
                        f'GenerateCoverThumbnails task has been ended.')
                    return

            if total_generated == 0:
                self.self_cleanup = True

        self._handleSuccess()
        self.app_db_session.remove()
Ejemplo n.º 10
0
 def name(self):
     return N_('Cover Thumbnails')
Ejemplo n.º 11
0
#
#  You should have received a copy of the GNU General Public License
#  along with this program. If not, see <http://www.gnu.org/licenses/>.

import os
import re

from flask_babel import lazy_gettext as N_

from . import config, logger
from .subproc_wrapper import process_wait

log = logger.create()

# strings getting translated when used
_NOT_INSTALLED = N_('not installed')
_EXECUTION_ERROR = N_('Execution permissions missing')


def _get_command_version(path, pattern, argument=None):
    if os.path.exists(path):
        command = [path]
        if argument:
            command.append(argument)
        try:
            match = process_wait(command, pattern=pattern)
            if isinstance(match, re.Match):
                return match.string
        except Exception as ex:
            log.warning("%s: %s", path, ex)
            return _EXECUTION_ERROR
Ejemplo n.º 12
0
 def name(self):
     return N_("Convert")
Ejemplo n.º 13
0
    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 = u'.' + self.settings['old_book_format'].lower()
        format_new_ext = u'.' + 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 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_("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_(u"Calibre ebook-convert %(tool)s not found",
                       tool=config.config_converterpath))
                return
            check, error_message = self._convert_calibre(
                file_path, format_old_ext, format_new_ext)

        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')
        self._handleError(error_message)
        return
Ejemplo n.º 14
0
 def name(self):
     return N_("Upload")
Ejemplo n.º 15
0
 def __init__(self, task_message=N_('Reconnecting Calibre database')):
     super(TaskReconnectDatabase, self).__init__(task_message)
     self.log = logger.create()
     self.listen_address = config.get_config_ipaddress()
     self.listen_port = config.config_port
Ejemplo n.º 16
0
 def name(self):
     return N_("E-mail")