aboutsummaryrefslogtreecommitdiff
path: root/src/book_store.py
blob: ece541511e650125b120772de225f7756ad1b321 (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
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 = 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:
                update_books(directory, books)
            if not already_exist(directory, books) or has_delete(library, book_id, 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(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):
    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