import nanoid import os from PIL import Image import pathlib import shutil import glob import logging import src.db as db logger = logging.getLogger(__name__) def store(library, conn, data, cover, books, book = None): book_id = book['id'] if book else nanoid.generate() directory = f'{library}/{book_id}' try: os.makedirs(directory, exist_ok=True) save_cover(cover, directory) if book: if not already_exist(directory, books) or has_delete(directory, books): update_books(directory, books) else: create_books(directory, books) if book: db.update_book(conn, book_id, data) else: db.create_book(conn, book_id, data) return book_id except Exception as err: if book: logger.error(f'Error updating book: %s', err) else: logger.error(f'Error creating book: %s', err) shutil.rmtree(directory, ignore_errors=True) db.delete_book(conn, book_id) return None def already_exist(directory, books): for path, name in books.items(): ext = path.suffix dest = f'{directory}/{name}{ext}' if not dest == str(path): return False return True def has_delete(directory, books): new_paths = books.keys() for path in glob.glob(f'{directory}/*'): if not path in new_paths: return True return False def update_books(directory, books): try: tmp_dir = f'{directory}/tmp' os.makedirs(tmp_dir, exist_ok=True) # Copy books to tmp directory for i, path in enumerate(books.keys()): dest = f'{tmp_dir}/{i}' logger.info('Copying %s to %s', path, dest) shutil.copyfile(path, dest) # Remove existing files (except cover.png and tmp) for path in glob.glob(f'{directory}/*'): bn = os.path.basename(path) if bn not in ['cover.png', 'cover-min.png', 'tmp']: logger.info('Removing %s', path) pathlib.Path.unlink(path) # Move from tmp to directory for i, path in enumerate(books.keys()): src = f'{tmp_dir}/{i}' ext = path.suffix name = books[path] dest = f'{directory}/{name}{ext}' logger.info('Copying %s to %s', src, dest) shutil.copyfile(src, dest) finally: # Remove tmp shutil.rmtree(f'{directory}/tmp', ignore_errors=True) def create_books(directory, books): for path, name in books.items(): ext = path.suffix shutil.copy(path, f'{directory}/{name}{ext}') # Save as PNG def save_cover(image, directory): image = image.convert('RGB') image.save(f'{directory}/cover.png', 'Png', optimize=True, quality=85) image_min = resize(image, 200) image_min.save(f'{directory}/cover-min.png', 'Png', optimize=True, quality=85) def resize(image, new_width): width, height = image.size if width > new_width: image = image.resize((new_width, int(new_width * height / width)), Image.LANCZOS) return image