aboutsummaryrefslogtreecommitdiff
path: root/src/book_store.py
blob: 71455bd4ec440f82fd2e23baf7f20c0ca9a1795c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import nanoid
import os
from PIL import Image
import pathlib
import shutil
import glob
import logging

import src.db as db
import src.book_files as book_files

logger = logging.getLogger(__name__)

def store(library, conn, data, cover, books, book, remove_book_sources):
    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(library, book_id, books):
                update_books(directory, books, remove_book_sources)
        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(library, book_id, books):
    new_paths = books.keys()
    for path in book_files.get(library, book_id):
        if not path in new_paths:
            return True
    return False

def update_books(directory, books, remove_book_sources):
    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)
        # Remove sources outside of book dir
        if remove_book_sources:
            for path in books.keys():
                if os.path.dirname(path) != directory:
                    logger.info('Removing source: %s', path)
                    pathlib.Path.unlink(path)
    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