diff options
author | 2020-01-31 13:48:31 +0100 | |
---|---|---|
committer | 2020-01-31 13:57:55 +0100 | |
commit | e8fc5c668953ef79de036da528fdb6d5387326e1 (patch) | |
tree | 47dc85a4787f36465c8640d786bff63f46146931 | |
parent | 6e97e651b647dda05acea45847bf52785e2e6244 (diff) | |
download | eshelf-master.tar.gz eshelf-master.tar.xz eshelf-master.zip |
- Allow opening of a local database
- Fix some bugs
- Rename ReaderOrm to Library
-rw-r--r-- | eshelf/cli.py | 188 | ||||
-rw-r--r-- | eshelf/library.py (renamed from eshelf/reader_orm.py) | 43 | ||||
-rw-r--r-- | eshelf/utils.py | 2 | ||||
-rw-r--r-- | eshelf/wizard.py | 2 |
4 files changed, 134 insertions, 101 deletions
diff --git a/eshelf/cli.py b/eshelf/cli.py index 0f632eb..c8aeef4 100644 --- a/eshelf/cli.py +++ b/eshelf/cli.py @@ -1,20 +1,21 @@ import os import re import sys +import shutil import argparse from configparser import ConfigParser from eshelf.wizard import setup_local_library from eshelf.bookeen import identify -from eshelf.reader_orm import ReaderOrm +from eshelf.library import Library from eshelf.utils import print_file_tree, print_listing, read_file, \ Logger class EShelfCli: def __init__(self): - self.reader_db = None - predefined_actions = ['help', 'books', 'collections', 'add', - 'remove', 'edit', 'init', 'list', + self.library_db = None + predefined_actions = ['help', 'books', 'collections', + 'add', 'remove', 'init', 'list', 'device'] parser = argparse.ArgumentParser(prog='eshelf') @@ -27,6 +28,8 @@ class EShelfCli: help='Path to your library.') parser.add_argument('--no-color', action='store_true', help='Remove colors from output.') + parser.add_argument('--remote', action='store_true', + help='Directly works on remote database') args = parser.parse_args() if args.command == 'help': @@ -68,9 +71,14 @@ class EShelfCli: self.exit(1) self.reader_mount_point = self.config['reader_mount_point'].rstrip('/') - self.reader_db = ReaderOrm( - os.path.join(self.reader_mount_point, 'system', 'library') + self.remote_db_path = os.path.join( + self.reader_mount_point, 'system', 'library' ) + self.local_db_path = os.path.join(library_path, 'library') + if args.remote: + self.library_db = Library(self.remote_db_path) + else: + self.library_db = Library(self.local_db_path) self.remote_physical_path = self.config.get( 'remote_physical_path', '/mnt/fat' @@ -80,13 +88,13 @@ class EShelfCli: self.bye() def bye(self, return_code=0): - if self.reader_db.is_opened(): - self.reader_db.close() + if self.library_db.is_opened(): + self.library_db.close() sys.exit(return_code) def cmd_collections(self, opts=[]): finaldata = [] - for data in self.reader_db.list_shelves(): + for data in self.library_db.list_shelves(): finaldata.append( '[{id}] {name}'.format( id=self.logger.hilite(data['id'], 'yellow'), @@ -99,72 +107,6 @@ class EShelfCli: ) print_listing('Collections:', finaldata) - def cmd_books(self, opts=[]): - shelf_name = None - shelf_id = None - orphans = False - if len(opts) == 1: - if opts[0] == 'orphans': - orphans = True - else: - shelf_infos = self.reader_db.get_shelf(opts[0]) - if shelf_infos is None: - return - shelf_name = shelf_infos['name'] - shelf_id = shelf_infos['id'] - finaldata = [] - remote_library_path = os.path.join( - self.remote_physical_path, - self.config['remote_library_path'] - ) - for book_data in self.reader_db.list_shelf_items(shelf_id): - if not book_data['internal_uri'].startswith(remote_library_path): - # Maybe a system file? Or a default one? - continue - - mounted_file_path = re.sub( - self.remote_physical_path, - self.reader_mount_point, - book_data['internal_uri'] - ) - - relative_file_path = re.sub( - remote_library_path, '', - book_data['internal_uri'] - ).lstrip('/') - - lfile = os.path.join(self.library_path, relative_file_path) - local_file = '' - if orphans: - if os.path.isfile(lfile): - continue - local_file = ' ' + mounted_file_path - elif not os.path.isfile(lfile): - local_file = ' (only on ereader: {0})' \ - .format(relative_file_path) - else: - local_file = ' ({0})'.format(relative_file_path) - - if os.path.isfile(mounted_file_path): - finaldata.append( - '[{id}] {title} — {author}{other}'.format( - id=self.logger.hilite(book_data['id'], 'yellow'), - title=self.logger.hilite( - book_data['title'], - color='cyan', - bold=True - ), - author=self.logger.hilite(book_data['author'], 'blue'), - other=local_file - ) - ) - - if shelf_name is not None: - title = 'Books in {0}:'.format(shelf_name) - else: - title = 'Books in your eReader library:' - print_listing(title, finaldata) - def cmd_list(self, opts=[]): if len(opts) == 1 and opts[0] == 'remote': print('Here is your eReader content:') @@ -176,10 +118,10 @@ class EShelfCli: print_file_tree(self.library_path) def prepare_add_remove(self, shelf_id_or_name, book_id_or_title): - shelf_infos = self.reader_db.get_shelf(shelf_id_or_name) + shelf_infos = self.library_db.get_shelf(shelf_id_or_name) if shelf_infos is None: self.bye(1) - book_infos = self.reader_db.get_book(book_id_or_title) + book_infos = self.library_db.get_book(book_id_or_title) if book_infos is None: self.bye(1) return shelf_infos['id'], book_infos['id'] @@ -190,7 +132,7 @@ class EShelfCli: ' <shelf_id_or_name>') self.bye(1) cur_shelf, cur_book = self.prepare_add_remove(opts[1], opts[0]) - self.reader_db.add_shelf_link(cur_book, cur_shelf) + self.library_db.add_shelf_link(cur_book, cur_shelf) print('Successfully added a book to a shelf.') self.books([cur_shelf]) @@ -200,18 +142,94 @@ class EShelfCli: ' <shelf_id_or_name>') self.bye(1) cur_shelf, cur_book = self.prepare_add_remove(opts[1], opts[0]) - self.reader_db.remove_shelf_link(cur_book, cur_shelf) + self.library_db.remove_shelf_link(cur_book, cur_shelf) print('Successfully removed a book from a shelf.') self.books([cur_shelf]) - def cmd_edit(self, opts=[]): + def cmd_books(self, opts=[]): + shelf_name = None + shelf_id = None + if len(opts) > 0: + if opts[0] == 'edit': + return self.book_edit(opts[1:]) + elif opts[0] == 'list': + opts = opts[1:] + # By default it's a list command + shelf_infos = len(opts) == 1 and self.library_db.get_shelf(opts[0]) + if not shelf_infos: + # May be False or None + return + shelf_name = shelf_infos['name'] + shelf_id = shelf_infos['id'] + finaldata = [] + remote_library_path = os.path.join( + self.remote_physical_path, + self.config['remote_library_path'] + ) + check_remote = True + if not os.path.isfile(self.remote_db_path): + print('eReader seems to be unmounted. Skipping remote check.') + check_remote = False + + for book_data in self.library_db.list_shelf_items(shelf_id): + if not book_data['internal_uri'].startswith(remote_library_path): + # Maybe a system file? Or a default one? + continue + + mounted_file_path = re.sub( + self.remote_physical_path, + self.reader_mount_point, + book_data['internal_uri'] + ) + + relative_file_path = re.sub( + remote_library_path, + '', + book_data['internal_uri'] + ).lstrip('/') + + local_file_path = os.path.join( + self.library_path, + relative_file_path + ) + + file_info = [] + if not os.path.isfile(local_file_path): + file_info.append('not present on computer') + if check_remote and not os.path.isfile(mounted_file_path): + file_info.append('not present on eReader') + warnings = ', '.join(file_info) + if warnings != '': + warnings = '(' + warnings + ')' + book_id = '[' + str(book_data['id']) + ']' + + book_line = '{id} {title} — {author} — {path} {warnings}' + finaldata.append(book_line.format( + id=self.logger.hilite(book_id, 'yellow'), + title=self.logger.hilite( + book_data['title'], + color='cyan', + bold=True + ), + author=self.logger.hilite(book_data['author'], 'blue'), + path=relative_file_path, + warnings=self.logger.hilite(warnings, color='red', bold=True) + )) + + if shelf_name is not None: + title = 'Books in {0}:'.format(shelf_name) + else: + title = 'Books in your library:' + print_listing(title, finaldata) + + def book_edit(self, opts=[]): if len(opts) < 2: print('Action must follow the form: edit <id> <new_title>') self.bye(1) - book_infos = self.reader_db.get_book(opts[0]) + book_infos = self.library_db.get_book(opts[0]) if book_infos is None: self.bye(1) - self.reader_db.update_book_title(book_infos['id'], opts[1]) + self.library_db.update_book(book_infos['id'], 'title', opts[1]) print('Title successfully updated to {0}.'.format(opts[1])) def cmd_device(self, opts=[]): @@ -245,6 +263,12 @@ class EShelfCli: print('Device serial: {0}'.format(p_sn)) print('Adobe serial: {0}'.format(adobe_sn)) + def cmd_pull(self, opts=[]): + shutil.copy(self.remote_db_path, self.library_path) + + def cmd_push(self, opts=[]): + shutil.copy(self.local_db_path, self.remote_db_path) + if __name__ == '__main__': EShelfCli() diff --git a/eshelf/reader_orm.py b/eshelf/library.py index 1055304..30b7177 100644 --- a/eshelf/reader_orm.py +++ b/eshelf/library.py @@ -1,30 +1,33 @@ import sqlite3 -class ReaderOrm: +class Library: def __init__(self, db_path): - self.reader_db = self.open_reader_db(db_path) + self.db_path = None + self.library_db = self.open_library_db(db_path) + if self.is_opened(): + self.db_path = db_path - def open_reader_db(self, db_path): + def open_library_db(self, db_path): try: - reader_db = sqlite3.connect(db_path) - reader_db.row_factory = sqlite3.Row - reader_db.isolation_level = None + library_db = sqlite3.connect(db_path) + library_db.row_factory = sqlite3.Row + library_db.isolation_level = None except sqlite3.OperationalError: - print('Something wrong happen. Maybe you do not have' - ' mounted your ereader.') + print('An unexpected error happens while opening the ' + 'library db.') return None - return reader_db + return library_db def is_opened(self): - return self.reader_db is not None + return self.library_db is not None def close(self): - if self.reader_db is not None: - self.reader_db.close() + if self.is_opened(): + self.library_db.close() def get_cursor(self): - return self.reader_db.cursor() + return self.library_db.cursor() def get_b_uuid(self): b_uuid_req = 'select f_db_uuid from t_uuiddb limit 1' @@ -106,7 +109,7 @@ class ReaderOrm: return [self.format_book_infos(row) for row in cur.execute(base_req)] base_req = ''' - select i.f_id_item, i.f_title, a.f_name + select i.f_id_item, i.f_title, i.f_internal_uri, a.f_name from t_item i inner join t_shelf_link s on s.f_item_id = i.f_id_item left join t_author a on a.f_id_author = i.f_author_id @@ -128,22 +131,26 @@ class ReaderOrm: return [self.format_shelf_infos(row) for row in cur.execute(query)] def add_shelf_link(self, book_id, shelf_id): - b_uuid = self.reader_db.get_b_uuid() + b_uuid = self.get_b_uuid() self.get_cursor().execute( 'insert into t_shelf_link values (?, ?, ?)', (book_id, shelf_id, b_uuid) ) def remove_shelf_link(self, book_id, shelf_id): - b_uuid = self.reader_db.get_b_uuid() + b_uuid = self.get_b_uuid() self.get_cursor().execute( 'delete from t_shelf_link where ' 'f_item_id = ? and f_shelf_id = ? and f_db_uuid = ?', (book_id, shelf_id, b_uuid) ) - def update_book_title(self, book_id, new_title): + def update_book(self, book_id, field, new_title): + if field == 'author': + field = 'f_author' + else: + field = 'f_title' self.get_cursor().execute( - 'update t_item set f_title = ? where f_id_item = ?', + 'update t_item set {} = ? where f_id_item = ?'.format(field), (new_title, book_id) ) diff --git a/eshelf/utils.py b/eshelf/utils.py index 7061cbd..b675442 100644 --- a/eshelf/utils.py +++ b/eshelf/utils.py @@ -15,7 +15,7 @@ def print_file_tree(current_dir, padding=None): raw_file_list = os.listdir(current_dir) file_list = list(filter( - lambda x: x != '.eshelf.conf', + lambda x: x not in ['.eshelf.conf', 'library'], raw_file_list, )) list_len = len(file_list) diff --git a/eshelf/wizard.py b/eshelf/wizard.py index 91cf7b2..c3c9119 100644 --- a/eshelf/wizard.py +++ b/eshelf/wizard.py @@ -1,5 +1,6 @@ import os import sys +import shutil from configparser import ConfigParser @@ -21,6 +22,7 @@ def setup_local_library(library_path): print('We cannot locate your eReader. ' 'Please check you have plugged it.') sys.exit(1) + shutil.copy(reader_db_path, library_path) confparser['DEFAULT']['reader_mount_point'] = reader_mount_point |