def process_file(infile, kindle_dir, width, height, stretch, verbose): global count_files, count_located, count_processed count_files += 1 if not os.path.exists(infile): if verbose: print('WARNING: File {0} not found'.format(infile)) return count_located += 1 if verbose: print('Processing file {}'.format(infile)) try: reader = mobi_read(infile, width, height, stretch) asin = reader.getCdeContentKey() if len(asin) == 0: asin = reader.getASIN() if len(asin) > 0: thumb = reader.getThumbnail() if thumb != None: thumb.convert('RGB').save(os.path.join(kindle_dir, 'thumbnail_' + asin + '_' + reader.getCdeType() + '_portrait.jpg'), 'JPEG') count_processed += 1 if verbose: print('Written thumbnail for {}'.format(asin)) else: if verbose: print("Skipping - no cover or thumbnail") else: if verbose: print("Skipping - no ASIN") except: print('ERROR: processing file.') traceback.print_exc() return
def process_file(infile, kindle_dir, verbose): global count_files, count_located, count_processed count_files += 1 if not os.path.exists(infile): if verbose: print('WARNING: File {0} not found'.format(infile)) return count_located += 1 if verbose: print('Processing file {}'.format(infile)) try: reader = mobi_read(infile) asin = reader.getASIN() if len(asin) > 0: thumb = reader.getThumbnail() if thumb != None: thumb.convert('RGB').save(os.path.join(kindle_dir, 'thumbnail_' + asin + '_EBOK_portrait.jpg'), 'JPEG') count_processed += 1 if verbose: print('Written thumbnail for {}'.format(asin)) else: if verbose: print("Skipping - no cover or thumbnail") else: if verbose: print("Skipping - no ASIN") except: print('ERROR: processing file.') traceback.print_exc() return
def process_file(config, infile, outfile=None): critical_error = False start_time = time.clock() temp_dir = tempfile.mkdtemp() if not os.path.exists(infile): config.log.critical('File {0} not found'.format(infile)) return config.log.info('Converting "{0}"...'.format(os.path.split(infile)[1])) config.log.info('Using profile "{0}".'.format( config.current_profile['name'])) # Проверка корректности параметров if infile: if not infile.lower().endswith(('.fb2', '.fb2.zip', '.zip', '.epub')): config.log.critical( '"{0}" not *.fb2, *.fb2.zip, *.zip or *.epub'.format(infile)) return if not config.current_profile['css'] and not infile.lower().endswith( ('.epub')): config.log.warning('Profile does not have link to css file.') if 'xslt' in config.current_profile and not os.path.exists( config.current_profile['xslt']): config.log.critical('Transformation file {0} not found'.format( config.current_profile['xslt'])) return if config.kindle_compression_level < 0 or config.kindle_compression_level > 2: config.log.warning( 'Parameter kindleCompressionLevel should be between 0 and 2, using default value (1).' ) config.kindle_compression_level = 1 # Если не задано имя выходного файла - вычислим if not outfile: outdir, outputfile = os.path.split(infile) outputfile = get_mobi_filename(outputfile, config.transliterate) if config.output_dir: if not os.path.exists(config.output_dir): os.makedirs(config.output_dir) if config.input_dir and config.save_structure: rel_path = os.path.join( config.output_dir, os.path.split(os.path.relpath(infile, config.input_dir))[0]) if not os.path.exists(rel_path): os.makedirs(rel_path) outfile = os.path.join(rel_path, outputfile) else: outfile = os.path.join(config.output_dir, outputfile) else: outfile = os.path.join(outdir, outputfile) else: _output_format = os.path.splitext(outfile)[1].lower()[1:] if _output_format not in ('mobi', 'azw3', 'epub'): config.log.critical( 'Unknown output format: {0}'.format(_output_format)) return -1 else: if not config.mhl: config.output_format = _output_format outfile = '{0}.{1}'.format( os.path.splitext(outfile)[0], config.output_format) if config.output_format.lower() == 'epub': # Для epub всегда разбиваем по главам config.current_profile['chapterOnNewPage'] = True debug_dir = os.path.abspath(os.path.splitext(infile)[0]) if os.path.splitext(debug_dir)[1].lower() == '.fb2': debug_dir = os.path.splitext(debug_dir)[0] input_epub = False if os.path.splitext(infile)[1].lower() == '.zip': config.log.info('Unpacking...') tmp_infile = infile try: infile = unzip(infile, temp_dir) except: config.log.critical( 'Error unpacking file "{0}".'.format(tmp_infile)) return if not infile: config.log.critical( 'Error unpacking file "{0}".'.format(tmp_infile)) return elif os.path.splitext(infile)[1].lower() == '.epub': config.log.info('Unpacking epub...') tmp_infile = infile try: infile = unzip_epub(infile, temp_dir) except: config.log.critical( 'Error unpacking file "{0}".'.format(tmp_infile)) return if not infile: config.log.critical( 'Error unpacking file "{0}".'.format(tmp_infile)) return input_epub = True if input_epub: # Let's see what we could do config.log.info('Processing epub...') epubparser = EpubProc(infile, config) epubparser.process() document_id = epubparser.book_uuid else: # Конвертируем в html config.log.info('Converting fb2 to html...') try: fb2parser = Fb2XHTML(infile, outfile, temp_dir, config) fb2parser.generate() document_id = fb2parser.book_uuid infile = os.path.join(temp_dir, 'OEBPS', 'content.opf') except: config.log.critical( 'Error while converting file "{0}"'.format(infile)) config.log.debug('Getting details', exc_info=True) return config.log.info('Processing took {0} sec.'.format( round(time.clock() - start_time, 2))) if config.output_format.lower() in ('mobi', 'azw3'): # Запускаем kindlegen application_path = get_executable_path() if sys.platform == 'win32': if os.path.exists(os.path.join(application_path, 'kindlegen.exe')): kindlegen_cmd = os.path.join(application_path, 'kindlegen.exe') else: kindlegen_cmd = 'kindlegen.exe' else: if os.path.exists(os.path.join(application_path, 'kindlegen')): kindlegen_cmd = os.path.join(application_path, 'kindlegen') else: kindlegen_cmd = 'kindlegen' try: config.log.info('Running kindlegen...') kindlegen_cmd_pars = '-c{0}'.format( config.kindle_compression_level) startupinfo = None if os.name == 'nt': startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW with subprocess.Popen( [kindlegen_cmd, infile, kindlegen_cmd_pars, '-locale', 'en'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, startupinfo=startupinfo) as result: config.log.debug( str(result.stdout.read(), 'utf-8', errors='replace')) except OSError as e: if e.errno == os.errno.ENOENT: config.log.critical('{0} not found'.format(kindlegen_cmd)) critical_error = True else: if sys.platform == 'win32': config.log.critical(e.winerror) config.log.critical(e.strerror) config.log.debug('Getting details', exc_info=True, stack_info=True) raise e elif config.output_format.lower() == 'epub': # Собираем epub outfile = os.path.splitext(outfile)[0] + '.epub' config.log.info('Creating epub...') create_epub(temp_dir, outfile) if config.debug: # В режиме отладки копируем получившиеся файлы в выходной каталог config.log.info( 'Copying intermediate files to {0}...'.format(debug_dir)) if os.path.exists(debug_dir): rm_tmp_files(debug_dir) shutil.copytree(temp_dir, debug_dir) if not input_epub: # Store fb2 after xslt transformation for debugging fb2parser.write_debug(debug_dir) # Копируем mobi(azw3) из временного в выходной каталог if not critical_error: ext = config.output_format.lower() if ext in ('mobi', 'azw3'): result_book = infile.replace('.opf', '.mobi') if not os.path.isfile(result_book): config.log.critical('kindlegen error, conversion interrupted.') critical_error = True else: try: remove_personal = config.current_profile[ 'kindleRemovePersonalLabel'] if ext in 'mobi' and config.noMOBIoptimization: config.log.info('Copying resulting file...') shutil.copyfile(result_book, outfile) else: config.log.info('Optimizing resulting file...') splitter = mobi_split(result_book, document_id, remove_personal, ext) open(os.path.splitext(outfile)[0] + '.' + ext, 'wb').write(splitter.getResult() if ext == 'mobi' else splitter.getResult8()) except: config.log.critical( 'Error optimizing file, conversion interrupted.') config.log.debug('Getting details', exc_info=True, stack_info=True) critical_error = True if config.apnx: try: base = os.path.splitext(outfile)[0] reader = mobi_read(base + '.' + ext) pagedata = reader.getPageData() if len(pagedata) > 0: config.log.info('Generating page index (APNX)...') pages = PageMapProcessor(pagedata, config.log) asin = reader.getCdeContentKey() if len(asin) == 0: asin = reader.getASIN() apnx = pages.generateAPNX({ 'contentGuid': str(uuid.uuid4()).replace('-', '')[:8], 'asin': asin, 'cdeType': reader.getCdeType(), 'format': 'MOBI_8' if ext in 'azw3' else 'MOBI_7', 'pageMap': pages.getPageMap(), 'acr': reader.getACR() }) if config.apnx == 'eink': basename = os.path.basename(base) sdr = base + '.sdr' if not os.path.exists(sdr): os.makedirs(sdr) apnxfile = os.path.join( sdr, basename + '.apnx') else: apnxfile = base + '.apnx' open(apnxfile, 'wb').write(apnx) else: config.log.warning( 'No information to generate page index') except: config.log.warning( 'Unable to generate page index (APNX)') config.log.debug('Getting details', exc_info=True, stack_info=True) if not critical_error: config.log.info('Book conversion completed in {0} sec.\n'.format( round(time.clock() - start_time, 2))) if config.send_to_kindle['send']: if config.output_format.lower() != 'mobi': config.log.warning( 'Kindle Personal Documents Service only accepts personal mobi files' ) else: config.log.info('Sending book...') try: kindle = SendToKindle() kindle.smtp_server = config.send_to_kindle['smtpServer'] kindle.smtp_port = config.send_to_kindle['smtpPort'] kindle.smtp_login = config.send_to_kindle['smtpLogin'] kindle.smtp_password = config.send_to_kindle[ 'smtpPassword'] kindle.user_email = config.send_to_kindle['fromUserEmail'] kindle.kindle_email = config.send_to_kindle[ 'toKindleEmail'] kindle.convert = False kindle.send_mail([outfile]) config.log.info('Book has been sent to "{0}"'.format( config.send_to_kindle['toKindleEmail'])) if config.send_to_kindle['deleteSendedBook']: try: os.remove(outfile) except: config.log.error( 'Unable to remove file "{0}".'.format(outfile)) return -1 except KeyboardInterrupt: print('User interrupt. Exiting...') sys.exit(-1) except: config.log.error('Error sending file') config.log.debug('Getting details', exc_info=True, stack_info=True) # Чистим временные файлы rm_tmp_files(temp_dir)
def process_file(config, infile, outfile=None): start_time = time.clock() temp_dir = tempfile.mkdtemp() if not os.path.exists(infile): config.log.critical('File {0} not found'.format(infile)) return fbname = os.path.basename(infile) config.log.info('Converting "{0}" in "{1}"...'.format(fbname, temp_dir)) config.log.info('Using profile "{0}".'.format( config.current_profile['name'])) # Проверка корректности параметров if infile: if not infile.lower().endswith(('.fb2', '.fb2.zip', '.zip', '.epub')): config.log.critical( '"{0}" not *.fb2, *.fb2.zip, *.zip or *.epub'.format(infile)) return if not config.current_profile['css'] and not infile.lower().endswith( ('.epub')): config.log.warning('Profile does not have link to css file.') if 'xslt' in config.current_profile and not os.path.exists( config.current_profile['xslt']): config.log.critical('Transformation file {0} not found'.format( config.current_profile['xslt'])) return if config.kindle_compression_level < 0 or config.kindle_compression_level > 2: config.log.warning( 'Parameter kindleCompressionLevel should be between 0 and 2, using default value (1).' ) config.kindle_compression_level = 1 # Если не задано имя выходного файла - вычислим if not outfile: outdir, outputfile = os.path.split(infile) outputfile = get_mobi_filename(outputfile, config.transliterate) if config.output_dir: if not os.path.exists(config.output_dir): os.makedirs(config.output_dir) if config.input_dir and config.save_structure: rel_path = os.path.join( config.output_dir, os.path.dirname(os.path.relpath(infile, config.input_dir))) if not os.path.exists(rel_path): os.makedirs(rel_path) outputfile = os.path.join(rel_path, outputfile) else: outputfile = os.path.join(config.output_dir, outputfile) else: outputfile = os.path.join(outdir, outputfile) else: _output_file, _output_format = os.path.splitext(outfile) if _output_format not in ('.mobi', '.azw3', '.epub'): config.log.critical( 'Output format "{0}" is not supported'.format(_output_format)) return else: _output_format = _output_format.lower()[1:] if not config.mhl: config.output_format = _output_format outputfile = '{0}.{1}'.format(_output_file, config.output_format) if config.output_format.lower() == 'epub': # Для epub всегда разбиваем по главам config.current_profile['chapterOnNewPage'] = True input_ext = os.path.splitext(infile)[1].lower() if input_ext == '.epub': config.log.info('Unpacking epub...') tmp_infile = infile try: infile = unzip_epub(infile, temp_dir) except: config.log.critical( 'Error unpacking file "{0}".'.format(tmp_infile)) return if not infile: config.log.critical( 'Error unpacking file "{0}".'.format(tmp_infile)) return # Let's see what we could do config.log.info('Processing epub...') epubparser = EpubProc(infile, config) epubparser.process() document_id = epubparser.book_uuid else: if input_ext == '.zip': config.log.info('Unpacking...') tmp_infile = infile try: infile = unzip(infile, temp_dir) except: config.log.critical( 'Error unpacking file "{0}".'.format(tmp_infile)) return if not infile: config.log.critical( 'Error unpacking file "{0}".'.format(tmp_infile)) return # Конвертируем в html config.log.info('Converting fb2 to html...') interrupted = False try: fb2parser = Fb2XHTML(infile, temp_dir, config) fb2parser.generate() document_id = fb2parser.book_uuid infile = os.path.join(temp_dir, 'OEBPS', 'content.opf') if not outfile and config.output_pattern: # pylint: disable=C0330 # yapf: disable fname = format_pattern(config.output_pattern, [ ('#title', '' if not fb2parser.book_title else fb2parser.book_title.strip()), ('#series', '' if not fb2parser.book_series else fb2parser.book_series.strip()), ('#abbrseries', ''.join(word[0] for word in fb2parser.book_series.split()).lower() if fb2parser.book_series else ''), ('#number', '' if not fb2parser.book_series_num else fb2parser.book_series_num.strip()), ('#padnumber', '' if not fb2parser.book_series_num else fb2parser.book_series_num.strip().zfill(fb2parser.seriespositions)), ('#authors', fb2parser.get_book_authors()), ('#author', fb2parser.get_book_authors(True)), ('#bookid', document_id), ]) # yapf: enable head, tail = os.path.splitext(outputfile) fname = clean_file_name(fname) config.log.info( 'Re-setting output file name to "{0}"...'.format(fname)) outputfile = os.path.join(os.path.dirname(head), fname + tail) except: interrupted = True config.log.critical( 'Error while converting file "{0}"'.format(infile)) config.log.debug('Getting details', exc_info=True) finally: if config.debug: # to avoid problems with file name length we'll base debug directory name on input file, but will place it in output file directory # part of the name will be number of seconds from epoc start - so name will be unique and easily sorted debug_dir = '{0}_debug_{1}'.format( os.path.join(os.path.dirname(outputfile), os.path.splitext(fbname)[0]), time.strftime("%Y%m%d%H%M%S")) # for debugging config.log.info( 'Copying intermediate files to "{0}"...'.format(debug_dir)) if os.path.exists(debug_dir): rm_tmp_files(debug_dir) shutil.copytree(temp_dir, debug_dir) if not input_ext == '.epub': # Store fb2 after xslt transformation for debugging fb2parser.write_debug(debug_dir) if interrupted: # pylint: disable=W0150 return config.log.info('Processing took {0} sec.'.format( round(time.clock() - start_time, 2))) if config.output_format.lower() in ('mobi', 'azw3'): # Запускаем kindlegen application_path = get_executable_path() kindlegen_cmd = 'kindlegen.exe' if version.WINDOWS else 'kindlegen' if os.path.exists(os.path.join(application_path, kindlegen_cmd)): kindlegen_cmd = os.path.join(application_path, kindlegen_cmd) interrupted = False try: config.log.info('Running kindlegen...') kindlegen_cmd_pars = '-c{0}'.format( config.kindle_compression_level) startupinfo = None if os.name == 'nt': startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW with subprocess.Popen( [kindlegen_cmd, infile, kindlegen_cmd_pars, '-locale', 'en'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, startupinfo=startupinfo) as result: config.log.debug( str(result.stdout.read(), 'utf-8', errors='replace')) except OSError as e: interrupted = True if e.errno == os.errno.ENOENT: config.log.critical('{0} not found'.format(kindlegen_cmd)) else: if version.WINDOWS: config.log.critical(e.winerror) config.log.critical(e.strerror) config.log.debug('Getting details', exc_info=True, stack_info=True) finally: if interrupted: rm_tmp_files(temp_dir) sys.exit(-1) elif config.output_format.lower() == 'epub': # Собираем epub config.log.info('Creating epub...') outputfile = os.path.splitext(outputfile)[0] + '.epub' create_epub(temp_dir, outputfile) ext = config.output_format.lower() if ext in ('mobi', 'azw3'): # Копируем mobi(azw3) из временного в выходной каталог result_book = infile.replace('.opf', '.mobi') if not os.path.isfile(result_book): config.log.critical('kindlegen error, conversion interrupted.') rm_tmp_files(temp_dir) return else: try: remove_personal = config.current_profile[ 'kindleRemovePersonalLabel'] if ext in 'mobi' and config.noMOBIoptimization: config.log.info('Copying resulting file...') shutil.copyfile(result_book, outputfile) else: config.log.info('Optimizing resulting file...') splitter = mobi_split(result_book, document_id, remove_personal, ext) open(os.path.splitext(outputfile)[0] + '.' + ext, 'wb').write(splitter.getResult() if ext == 'mobi' else splitter.getResult8()) except: config.log.critical( 'Error optimizing file, conversion interrupted.') config.log.debug('Getting details', exc_info=True, stack_info=True) rm_tmp_files(temp_dir) return if config.apnx: try: base, _ = os.path.splitext(outputfile) reader = mobi_read(base + '.' + ext) pagedata = reader.getPageData() if pagedata: config.log.info('Generating page index (APNX)...') pages = PageMapProcessor(pagedata, config.log) asin = reader.getCdeContentKey() if not asin: asin = reader.getASIN() apnx = pages.generateAPNX({ 'contentGuid': str(uuid.uuid4()).replace('-', '')[:8], 'asin': asin, 'cdeType': reader.getCdeType(), 'format': 'MOBI_8' if ext in 'azw3' else 'MOBI_7', 'pageMap': pages.getPageMap(), 'acr': reader.getACR() }) if config.apnx == 'eink': basename = os.path.basename(base) sdr = base + '.sdr' if not os.path.exists(sdr): os.makedirs(sdr) apnxfile = os.path.join(sdr, basename + '.apnx') else: apnxfile = base + '.apnx' open(apnxfile, 'wb').write(apnx) else: config.log.warning( 'No information to generate page index') except: config.log.warning('Unable to generate page index (APNX)') config.log.debug('Getting details', exc_info=True, stack_info=True) config.log.info('Book conversion completed in {0} sec.\n'.format( round(time.clock() - start_time, 2))) if config.send_to_kindle['send']: if config.output_format.lower() != 'mobi': config.log.warning( 'Kindle Personal Documents Service only accepts personal mobi files' ) else: config.log.info('Sending book...') try: kindle = SendToKindle() kindle.smtp_server = config.send_to_kindle['smtpServer'] kindle.smtp_port = config.send_to_kindle['smtpPort'] kindle.smtp_login = config.send_to_kindle['smtpLogin'] kindle.smtp_password = config.send_to_kindle['smtpPassword'] kindle.user_email = config.send_to_kindle['fromUserEmail'] kindle.kindle_email = config.send_to_kindle['toKindleEmail'] kindle.convert = False kindle.send_mail([outputfile]) config.log.info('Book has been sent to "{0}"'.format( config.send_to_kindle['toKindleEmail'])) if config.send_to_kindle['deleteSendedBook']: try: os.remove(outputfile) except: config.log.error( 'Unable to remove file "{0}".'.format(outputfile)) return except KeyboardInterrupt: print('User interrupt. Exiting...') rm_tmp_files(temp_dir) sys.exit(-1) except: config.log.error('Error sending file') config.log.debug('Getting details', exc_info=True, stack_info=True) # Чистим временные файлы rm_tmp_files(temp_dir) return os.path.splitext(outputfile)[0] + '.' + ext