From 1ebc55c72a1a17293bbf4ad86e0177a10a794750 Mon Sep 17 00:00:00 2001 From: Joris Date: Sun, 17 Sep 2023 12:23:47 +0200 Subject: Make app packageable --- src/new/__init__.py | 0 src/new/command.py | 94 ----------------------------------------------------- src/new/format.py | 76 ------------------------------------------- src/new/reader.py | 55 ------------------------------- 4 files changed, 225 deletions(-) delete mode 100644 src/new/__init__.py delete mode 100644 src/new/command.py delete mode 100644 src/new/format.py delete mode 100644 src/new/reader.py (limited to 'src/new') diff --git a/src/new/__init__.py b/src/new/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/new/command.py b/src/new/command.py deleted file mode 100644 index fe706c2..0000000 --- a/src/new/command.py +++ /dev/null @@ -1,94 +0,0 @@ -import PIL.Image -import io -import os -import pathlib -import re -import requests -import shutil -import subprocess -import sys -import unicodedata -import urllib.request - -import new.reader as reader -import new.format as format - -def run(book_library, book_source=None): - - # Get data - - title = reader.required('Title') - subtitle = reader.optional('Subtitle') - authors = reader.non_empty_list('Authors') - author_sort = reader.required('Authors sorting') - genres = reader.non_empty_list('Genres') - year = reader.integer('Year') - lang = reader.choices('Lang', ['fr', 'en', 'de']) - summary = format.cleanup_text(reader.multi_line('Summary'), lang) - cover_url = reader.required('Cover url') - read = reader.choices('Read', ['Read', 'Unread', 'Reading', 'Stopped']) - - # Output paths - - author_path = format.path_part(author_sort) - title_path = format.path_part(title) - - library_path = '/home/joris/documents/books' - output_dir = f'{library_path}/{author_path}/{title_path}' - metadata_path = f'{output_dir}/metadata.toml' - cover_path = f'{output_dir}/cover.webp' - - if not book_source is None: - ext = format.extension(book_source) - book_path = f'{output_dir}/book{ext}' - book_source_dir = os.path.dirname(os.path.realpath(book_source)) - book_source_new = f'{book_source_dir}/{author_path}-{title_path}.mobi' - - # Metadata - - metadata = f"""title = "{title}" - subtitle = "{subtitle}" - authors = {format.format_list(authors)} - authorsSort = "{author_sort}" - genres = {format.format_list(genres)} - date = {year} - summary = \"\"\" - {summary} - \"\"\" - read = "{read}" - """ - - # Ask for confirmation - - print(f'About to create:\n\n- {metadata_path}\n- {cover_path}') - if not book_source is None: - print(f'- {book_path}') - print(f'\nAnd moving:\n\n {book_source},\n -> {book_source_new}.') - print() - - reader.confirm('OK?') - - # Create files - - pathlib.Path(output_dir).mkdir(parents=True, exist_ok=True) - download_cover(cover_url, cover_path) - with open(metadata_path, 'w') as f: - f.write(metadata) - if not book_path is None: - shutil.copyfile(book_source, book_path) - if format.extension(book_source) in ['mobi', 'azw3']: - os.rename(book_source, book_source_new) - else: - subprocess.run(['ebook-convert', book_source, book_source_new]) - os.remove(book_source) - -# Download cover as WEBP -def download_cover(url, path): - response = requests.get(url, headers={ 'User-Agent': 'python-script' }) - image = PIL.Image.open(io.BytesIO(response.content)) - width, height = image.size - if width > 300: - image = image.resize((300, int(300 * height / width)), PIL.Image.LANCZOS) - image = image.convert('RGB') - image.save(path, 'WEBP', optimize=True, quality=85) - diff --git a/src/new/format.py b/src/new/format.py deleted file mode 100644 index a712544..0000000 --- a/src/new/format.py +++ /dev/null @@ -1,76 +0,0 @@ -import PIL.Image -import io -import os -import pathlib -import re -import requests -import shutil -import subprocess -import sys -import unicodedata -import urllib.request - -def format_list(xs): - return '[ ' + ', '.join([f'"{x}"' for x in xs]) + ' ]' - -def path_part(name): - simplified = ''.join([alnum_or_space(c) for c in unaccent(name.lower())]) - return '-'.join(simplified.split()) - -def unaccent(s): - return ''.join(c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn') - -def alnum_or_space(c): - if c.isalnum(): - return c - else: - return ' ' - -def extension(path): - return pathlib.Path(path).suffix - -def cleanup_text(s, lang): - s = re.sub('\'', '’', s) - s = re.sub('\.\.\.', '…', s) - s = re.sub('\. \. \.', '…', s) - s = cleanup_quotes(s, lang) - - if lang == 'fr': - s = re.sub('“', '«', s) - s = re.sub('”', '»', s) - - # Replace space by insecable spaces - s = re.sub(r' ([:?\!»])', r' \1', s) - s = re.sub('« ', '« ', s) - - # Add missing insecable spaces - s = re.sub(r'([^ ])([:?\!»])', r'\1 \2', s) - s = re.sub(r'«([^ ])', r'« \1', s) - - elif lang == 'en': - s = re.sub('«', '“', s) - s = re.sub('»', '”', s) - - return s - -def cleanup_quotes(s, lang): - res = '' - quoted = False - for c in s: - if c == '"': - if quoted: - quoted = False - if lang == 'fr': - res += '»' - elif lang == 'en': - res += '”' - else: - quoted = True - if lang == 'fr': - res += '«' - elif lang == 'en': - res += '“' - else: - res += c - return res - diff --git a/src/new/reader.py b/src/new/reader.py deleted file mode 100644 index eacd70b..0000000 --- a/src/new/reader.py +++ /dev/null @@ -1,55 +0,0 @@ -def required(label): - value = input(f'{label}: ').strip() - if value: - print() - return value - else: - return required(label) - -def multi_line(label): - lines = '' - print(f'{label}, type [end] to finish:\n') - while True: - value = input() - if value.strip() == '[end]': - break - elif value.strip(): - lines += f'{value.strip()}\n' - print() - return lines.strip() - -def optional(label): - value = input(f'{label} (optional): ').strip() - print() - return value - -def non_empty_list(label): - value = input(f'{label} (separated by commas): ') - values = [x.strip() for x in value.split(',') if x.strip()] - if len(values) > 0: - print() - return values - else: - return non_empty_list(label) - -def integer(label): - value = input(f'{label}: ').strip() - if value.isdigit(): - print() - return int(value) - else: - return integer(label) - -def choices(label, xs): - pp_choices = '/'.join(xs) - value = input(f'{label} [{pp_choices}] ') - if value in xs: - print() - return value - else: - return choices(label, xs) - -def confirm(message): - if choices(message, ['y', 'n']) == 'n': - print('\nStopping.') - exit(1) -- cgit v1.2.3