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
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
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?")
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
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()
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))
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()
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
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()
def name(self): return N_('Cover Thumbnails')
# # 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
def name(self): return N_("Convert")
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
def name(self): return N_("Upload")
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
def name(self): return N_("E-mail")