summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eshelf/cli.py188
-rw-r--r--eshelf/library.py (renamed from eshelf/reader_orm.py)43
-rw-r--r--eshelf/utils.py2
-rw-r--r--eshelf/wizard.py2
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