def fetch_selected_annotations(self): ''' Invoked by 'Import annotations' button in show_annotated_books_dialog() Populate a list of books by Reader App: { 'iBooks': [{'title':, 'author':, 'uuid'}, ...], 'Marvin': [{'title':, 'author':, 'uuid'}, ...] } ''' self.selected_books = {} for i in range(len(self.tabledata)): self.tv.selectRow(i) enabled = bool(self.tm.arraydata[i][self.ENABLED_COL].checkState()) if not enabled: continue reader_app = str(self.tm.arraydata[i][self.READER_APP_COL].text()) if not reader_app in self.selected_books: self.selected_books[reader_app] = [] author = str(self.tm.arraydata[i][self.AUTHOR_COL].text()) book_id = self.tm.arraydata[i][self.annotations_header.index( 'book_id')] genre = self.tm.arraydata[i][self.annotations_header.index( 'genre')] title = str(self.tm.arraydata[i][self.TITLE_COL].text()) uuid = self.tm.arraydata[i][self.annotations_header.index('uuid')] book_mi = BookStruct() book_mi.author = author book_mi.book_id = book_id book_mi.genre = genre book_mi.reader_app = reader_app book_mi.title = title book_mi.uuid = uuid self.selected_books[reader_app].append(book_mi)
def fetch_selected_annotations(self): ''' Invoked by 'Import annotations' button in show_annotated_books_dialog() Populate a list of books by Reader App: { 'iBooks': [{'title':, 'author':, 'uuid'}, ...], 'Marvin': [{'title':, 'author':, 'uuid'}, ...] } ''' self.selected_books = {} for i in range(len(self.tabledata)): self.tv.selectRow(i) enabled = bool(self.tm.arraydata[i][self.ENABLED_COL].checkState()) if not enabled: continue reader_app = str(self.tm.arraydata[i][self.annotations_header.index('Reader App')].text()) if not reader_app in self.selected_books: self.selected_books[reader_app] = [] author = str(self.tm.arraydata[i][self.annotations_header.index('Author')].text()) book_id = self.tm.arraydata[i][self.annotations_header.index('book_id')] genre = self.tm.arraydata[i][self.annotations_header.index('genre')] title = str(self.tm.arraydata[i][self.annotations_header.index('Title')].text()) uuid = self.tm.arraydata[i][self.annotations_header.index('uuid')] book_mi = BookStruct() book_mi.author = author book_mi.book_id = book_id book_mi.genre = genre book_mi.reader_app = reader_app book_mi.title = title book_mi.uuid = uuid self.selected_books[reader_app].append(book_mi)
def get_installed_books(self): ''' For each book, construct a BookStruct object with the book's metadata. Starred items are minimally required. BookStruct properties: *active: [True|False] *author: "John Smith" author_sort: (if known) *book_id: an int uniquely identifying the book. Highlights are associated with books through book_id genre: "Fiction" (if known) *reader_app: self.app_name *title: "The Story of John Smith" title_sort: "Story of John Smith, The" (if known) uuid: Calibre's uuid for this book, if known ''' self._log("%s:get_installed_books()" % self.app_name) self.opts.pb.set_label("Getting installed books from %s" % self.app_name) self.opts.pb.set_value(0) db_profile = self._localize_database_path(self.app_id, self.books_subpath) self.book_db = db_profile['path'] cached_db = self.generate_books_db_name(self.app_name_, self.ios.device_name) if self.opts.disable_caching or not self._cache_is_current( db_profile['stats'], cached_db): self._log(" fetching installed books from %s on %s" % (self.app_name, self.ios.device_name)) # Mount the ios container self.ios.mount_ios_app(app_id=self.app_id) installed_books = set([]) self.tocs = {} # Create the books table as needed self.create_books_table(cached_db) con = sqlite3.connect(self.books_db) with con: con.row_factory = sqlite3.Row cur = con.cursor() cur.execute('''SELECT DISTINCT author, oid, subject, source, title, uuidstr FROM book JOIN book_subjects ON book.oid = book_subjects.book_oid ''') rows = cur.fetchall() self.opts.pb.set_maximum(len(rows)) for row in rows: self.opts.pb.increment() book_id = row[b'oid'] installed_books.add(book_id) path = self._get_stanza_path(row[b'title']) # Populate a BookStruct b_mi = BookStruct() b_mi.active = True b_mi.author = row[b'author'] b_mi.book_id = book_id b_mi.genre = row[b'subject'] b_mi.path = path b_mi.title = row[b'title'] b_mi.uuid = self._get_uuid(row[b'uuidstr']) # Add book to books_db self.add_to_books_db(cached_db, b_mi) # Get the library cid, confidence cid, confidence = self.parent.generate_confidence(b_mi) toc_entries = None if confidence >= 2: toc_entries = self._get_epub_toc(cid=cid, path=path) elif path is not None: toc_entries = self._get_epub_toc(path=path) self.tocs[book_id] = toc_entries # Update the timestamp self.update_timestamp(cached_db) self.commit() installed_books = list(installed_books) else: # Load installed books from cache self._log(" retrieving cached books from %s" % cached_db) installed_books = self._get_cached_books(cached_db) self.installed_books = installed_books
def get_installed_books(self): ''' For each book, construct a BookStruct object with the book's metadata. Starred items are minimally required. BookStruct properties: *active: [True|False] *author: "John Smith" author_sort: (if known) *book_id: an int uniquely identifying the book. Highlights are associated with books through book_id genre: "Fiction" (if known) *reader_app: self.app_name *title: "The Story of John Smith" title_sort: "Story of John Smith, The" (if known) uuid: Calibre's uuid for this book, if known ''' self._log("%s:get_installed_books()" % self.app_name) self.installed_books = [] self.device = self.opts.gui.device_manager.device path_map = self.get_path_map() # Calibre already knows what books are on the device, so use it. db = self.opts.gui.library_view.model().db self.onDeviceIds = set( db.search_getting_ids('ondevice:True', None, sort_results=False, use_virtual_library=False)) # Add books added to Tolino by WhisperNet or download # resolved_path_map = self._get_imported_books(resolved_path_map) self.books_db = self.generate_books_db_name(self.app_name_, self.opts.device_name) installed_books = set([]) # Used by get_active_annotations() to look up metadata based on title self.installed_books_by_title = {} # Create the books table self.create_books_table(self.books_db) # Initialize the progress bar self.opts.pb.set_label("Getting installed books from %s" % self.app_name) self.opts.pb.set_value(0) self.opts.pb.show() self.opts.pb.set_maximum(len(self.onDeviceIds)) # Add installed books to the database for book_id in self.onDeviceIds: try: library_mi = mi = db.get_metadata(book_id, index_is_id=True) except Exception as e: self._log("Unable to get metadata from book. book_id='%s'" % (book_id)) self._log(" Exception thrown was=%s" % (str(e))) continue self._log("Book on device title: '%s'" % (mi.title)) for model in (self.opts.gui.memory_view.model(), self.opts.gui.card_a_view.model(), self.opts.gui.card_b_view.model()): model_paths = model.paths_for_db_ids(set([book_id]), as_map=True)[book_id] if model_paths: device_path = model_paths[0].path self._log(" Book on device path: '%s'" % (device_path, )) mi = self._get_metadata(device_path) # self._log(" Book on device path: '%s'" % (mi,)) break if 'News' in mi.tags: if not self.collect_news_clippings: continue installed_books.add(self.news_clippings_cid) else: installed_books.add(book_id) #self._log(mi.standard_field_keys()) # Populate a BookStruct with available metadata book_mi = BookStruct() # book_mi.path = resolved_path_map[book_id] # Required items book_mi.active = True # Massage last, first authors back to normalcy book_mi.author = '' for i, author in enumerate(mi.authors): this_author = author.split(', ') this_author.reverse() book_mi.author += ' '.join(this_author) if i < len(mi.authors) - 1: book_mi.author += ' & ' book_mi.book_id = book_id book_mi.reader_app = self.app_name book_mi.title = mi.title.strip() # Add book to indexed_books self.installed_books_by_title[mi.title] = { 'book_id': book_id, 'author_sort': mi.author_sort } # Optional items if mi.tags: book_mi.genre = ', '.join([tag for tag in mi.tags]) if 'News' in mi.tags: book_mi.book_id = self.news_clippings_cid if hasattr(mi, 'author_sort'): book_mi.author_sort = mi.author_sort self.installed_books_by_title[ mi.title]['author_sort'] = mi.author_sort if hasattr(mi, 'title_sort'): book_mi.title_sort = mi.title_sort else: book_mi.title_sort = re.sub('^\s*A\s+|^\s*The\s+|^\s*An\s+', '', mi.title).rstrip() if hasattr(library_mi, 'uuid'): self._log(" Book on has uuid: '%s'" % (library_mi.uuid, )) book_mi.uuid = library_mi.uuid self.installed_books_by_title[mi.title]['uuid'] = book_mi.uuid # Add book to self.books_db self.add_to_books_db(self.books_db, book_mi) # Increment the progress bar self.opts.pb.increment() self.opts.pb.hide() # Update the timestamp self.update_timestamp(self.books_db) self.commit() self.installed_books = list(installed_books)
def get_installed_books(self): ''' For each book, construct a BookStruct object with the book's metadata. Starred items are minimally required. BookStruct properties: *active: [True|False] *author: "John Smith" author_sort: (if known) *book_id: an int uniquely identifying the book. Highlights are associated with books through book_id genre: "Fiction" (if known) *reader_app: self.app_name *title: "The Story of John Smith" title_sort: "Story of John Smith, The" (if known) uuid: Calibre's uuid for this book, if known ''' # Sample installed books indexed by book_id dict_of_books = {} dict_of_books[1] = { 'author': 'John Smith', 'author_sort': 'Smith, John', 'title': 'The Book by John Smith', 'title_sort': 'Book by John Smith, The' } dict_of_books[2] = { 'author': 'William Jones', 'author_sort': 'Jones, William', 'title': 'Learning Programming', 'title_sort': 'Learning Programming' } dict_of_books[3] = { 'author': 'Matthew Williams', 'author_sort': 'Williams, Matthew', 'title': 'A Book With No Annotations', 'title_sort': 'Book With No Annotations, A' } self._log("%s:get_installed_books()" % self.app_name) self.installed_books = [] # Don't change the template of books_db string books_db = "%s_books_%s" % (re.sub( ' ', '_', self.app_name), re.sub(' ', '_', self.opts.device_name)) installed_books = set([]) # Create the books table self.create_books_table(books_db) # Initialize the progress bar self.opts.pb.set_label("Getting installed books from %s" % self.app_name) self.opts.pb.set_value(0) self.opts.pb.set_maximum(len(dict_of_books)) # Add installed books to the database for book_id in dict_of_books: # Add book_id to list of installed_books (make this a sql function) installed_books.add(book_id) # Populate a BookStruct with available metadata book_mi = BookStruct() # Required items book_mi.active = True book_mi.author = dict_of_books[book_id]['author'] book_mi.book_id = book_id book_mi.reader_app = self.app_name book_mi.title = dict_of_books[book_id]['title'] # Optional items if 'author_sort' in dict_of_books[book_id]: book_mi.author_sort = dict_of_books[book_id]['author_sort'] if 'genre' in dict_of_books[book_id]: book_mi.genre = dict_of_books[book_id]['genre'] if 'title_sort' in dict_of_books[book_id]: book_mi.title_sort = dict_of_books[book_id]['title_sort'] if 'uuid' in dict_of_books[book_id]: book_mi.uuid = dict_of_books[book_id]['uuid'] # Add book to books_db self.add_to_books_db(books_db, book_mi) # Increment the progress bar self.opts.pb.increment() # Update the timestamp self.update_timestamp(books_db) self.commit() self.installed_books = list(installed_books)
def get_installed_books(self): """ Fetch installed books from mainDb.sqlite or cached_db Populate self.tocs: {book_id: {toc_entries} ...} """ self._log("%s:get_installed_books()" % self.app_name) self.opts.pb.set_label("Getting installed books from %s" % self.app_name) self.opts.pb.set_value(0) db_profile = self._localize_database_path(self.app_id, self.books_subpath) self.books_db = db_profile['path'] cached_db = self.generate_books_db_name(self.app_name_, self.ios.device_name) if self.opts.disable_caching or not self._cache_is_current( db_profile['stats'], cached_db): # (Re)load installed books from device self._log(" fetching installed books from %s on %s" % (self.app_name, self.ios.device_name)) # Mount the ios container self.ios.mount_ios_app(app_id=self.app_id) installed_books = set([]) self.tocs = {} # Create the books table as needed self.create_books_table(cached_db) con = sqlite3.connect(self.books_db) with con: con.row_factory = sqlite3.Row cur = con.cursor() cur.execute('''SELECT Author, AuthorSort, Title, CalibreTitleSort, FileName, Books.ID AS id_, UUID FROM Books ''') rows = cur.fetchall() self.opts.pb.set_maximum(len(rows)) for row in rows: self.opts.pb.increment() this_is_news = False path = self._fix_Marvin_path(row[b'FileName']) book_id = row[b'id_'] # Get the genre(s) for this book genre_cur = con.cursor() genre_cur.execute("""SELECT Subject FROM BookSubjects WHERE BookID = '{0}' """.format(book_id)) genres = None genre_rows = genre_cur.fetchall() if genre_rows is not None: genres = ', '.join( [genre[b'Subject'] for genre in genre_rows]) genre_cur.close() if 'News' in genres: if not self.collect_news_clippings: continue this_is_news = True installed_books.add(book_id) # Populate a BookStruct b_mi = BookStruct() b_mi.active = True b_mi.author = row[b'Author'] b_mi.author_sort = row[b'AuthorSort'] b_mi.book_id = book_id b_mi.genre = genres b_mi.title = row[b'Title'] b_mi.title_sort = row[b'CalibreTitleSort'] b_mi.uuid = row[b'UUID'] # Add book to books_db self.add_to_books_db(cached_db, b_mi) # Get the library cid, confidence toc_entries = None if this_is_news: cid = self.news_clippings_cid confidence = 5 if path is not None: toc_entries = self._get_epub_toc( path=path, prepend_title=b_mi.title) else: cid, confidence = self.parent.generate_confidence(b_mi) if confidence >= 2: toc_entries = self._get_epub_toc(cid=cid, path=path) elif path is not None: toc_entries = self._get_epub_toc(path=path) self.tocs[book_id] = toc_entries # Update the timestamp self.update_timestamp(cached_db) self.commit() self.ios.disconnect_idevice() installed_books = list(installed_books) else: # Load installed books from cache self._log(" retrieving cached books from %s" % cached_db) self.opts.pb.set_maximum(2) self.opts.pb.set_value(1) Application.processEvents() installed_books = self._get_cached_books(cached_db) self.installed_books = installed_books
def get_installed_books(self): ''' For each book, construct a BookStruct object with the book's metadata. Starred items are minimally required. BookStruct properties: *active: [True|False] *author: "John Smith" author_sort: (if known) *book_id: an int uniquely identifying the book. Highlights are associated with books through book_id genre: "Fiction" (if known) *reader_app: self.app_name *title: "The Story of John Smith" title_sort: "Story of John Smith, The" (if known) uuid: Calibre's uuid for this book, if known ''' self._log("%s:get_installed_books()" % self.app_name) self.installed_books = [] self.device = self.opts.gui.device_manager.device path_map = self.get_path_map() # Get books added to Kindle by calibre resolved_path_map = self._get_installed_books(path_map) # Add books added to Kindle by WhisperNet or download resolved_path_map = self._get_imported_books(resolved_path_map) self.books_db = self.generate_books_db_name(self.app_name_, self.opts.device_name) installed_books = set([]) # Used by get_active_annotations() to look up metadata based on title self.installed_books_by_title = {} # Create the books table self.create_books_table(self.books_db) # Initialize the progress bar self.opts.pb.set_label("Getting installed books from %s" % self.app_name) self.opts.pb.set_value(0) self.opts.pb.show() self.opts.pb.set_maximum(len(resolved_path_map)) # Add installed books to the database for book_id in resolved_path_map: try: mi = self._get_metadata(resolved_path_map[book_id]) except Exception as e: self._log("Unable to get metadata from book. path='%s'" % (resolved_path_map[book_id])) self._log(" Exception thrown was=%s" % (str(e))) continue self._log("Book on device title: '%s'" % (mi.title)) if 'News' in mi.tags: if not self.collect_news_clippings: continue installed_books.add(self.news_clippings_cid) else: installed_books.add(book_id) #self._log(mi.standard_field_keys()) # Populate a BookStruct with available metadata book_mi = BookStruct() book_mi.path = resolved_path_map[book_id] # Required items book_mi.active = True # Massage last, first authors back to normalcy book_mi.author = '' for i, author in enumerate(mi.authors): this_author = author.split(', ') this_author.reverse() book_mi.author += ' '.join(this_author) if i < len(mi.authors) - 1: book_mi.author += ' & ' book_mi.book_id = book_id book_mi.reader_app = self.app_name book_mi.title = mi.title.strip() # Optional items if mi.tags: book_mi.genre = ', '.join([tag for tag in mi.tags]) if 'News' in mi.tags: book_mi.book_id = self.news_clippings_cid if hasattr(mi, 'author_sort'): book_mi.author_sort = mi.author_sort if hasattr(mi, 'title_sort'): book_mi.title_sort = mi.title_sort else: book_mi.title_sort = re.sub('^\s*A\s+|^\s*The\s+|^\s*An\s+', '', mi.title).rstrip() if hasattr(mi, 'uuid'): book_mi.uuid = mi.uuid # Add book to self.books_db self.add_to_books_db(self.books_db, book_mi) # Add book to indexed_books self.installed_books_by_title[mi.title.strip()] = {'book_id': book_id, 'author_sort': mi.author_sort} # Increment the progress bar self.opts.pb.increment() self.opts.pb.hide() # Update the timestamp self.update_timestamp(self.books_db) self.commit() self.installed_books = list(installed_books)
def get_installed_books(self): """ Fetch installed books from iBooks_*.sqlite or cache """ self._log("%s:get_installed_books()" % self.app_name) self.opts.pb.set_label("Getting installed books from %s" % self.app_name) self.opts.pb.set_value(0) db_profile = self._localize_database_path(self.app_id, self.books_subpath) self.books_db = db_profile['path'] cached_db = self.generate_books_db_name(self.app_name_, self.ios.device_name) # Test timestamp against cached value if self.opts.disable_caching or not self._cache_is_current( db_profile['stats'], cached_db): # (Re)load installed books from device self._log(" fetching installed books from %s on %s" % (self.app_name, self.ios.device_name)) # Mount the Media folder self.ios.mount_ios_media_folder() installed_books = set([]) self.tocs = {} # Create the books table as needed self.create_books_table(cached_db) con = sqlite3.connect(self.books_db) with con: con.row_factory = sqlite3.Row cur = con.cursor() cur.execute('''SELECT ZASSETURL, ZBOOKAUTHOR, ZSORTAUTHOR, ZBOOKTITLE, ZSORTTITLE, ZDATABASEKEY FROM ZBKBOOKINFO WHERE ZASSETURL LIKE 'file://localhost%' AND ZASSETURL LIKE '%.epub/' ''') rows = cur.fetchall() self.opts.pb.set_maximum(len(rows)) for row in rows: self.opts.pb.increment() this_is_news = False path = self._fix_iBooks_path(row[b'ZASSETURL']) mi = self._get_metadata(path, row[b'ZBOOKTITLE']) genres = mi['genre'].split(', ') if 'News' in genres: if not self.collect_news_clippings: continue this_is_news = True book_id = row[b'ZDATABASEKEY'] installed_books.add(book_id) # Populate a BookStruct b_mi = BookStruct() b_mi.active = True b_mi.author = row[b'ZBOOKAUTHOR'] b_mi.author_sort = row[b'ZSORTAUTHOR'] b_mi.book_id = book_id b_mi.genre = mi['genre'] b_mi.title = row[b'ZBOOKTITLE'] b_mi.title_sort = row[b'ZSORTTITLE'] b_mi.uuid = mi['uuid'] # Add book to books_db self.add_to_books_db(cached_db, b_mi) # Get the library cid, confidence toc_entries = None if this_is_news: cid = self.news_clippings_cid confidence = 5 if path is not None: toc_entries = self._get_epub_toc( path=path, prepend_title=b_mi.title) elif self.ios.exists(path): cid, confidence = self.parent.generate_confidence(b_mi) if confidence >= 2: toc_entries = self._get_epub_toc(cid=cid, path=path) elif path is not None: toc_entries = self._get_epub_toc(path=path) self.tocs[book_id] = toc_entries # Update the timestamp self.update_timestamp(cached_db) self.commit() self.ios.dismount_ios_media_folder() installed_books = list(installed_books) else: self._log(" retrieving cached books from %s" % cached_db) self.opts.pb.set_maximum(2) self.opts.pb.set_value(1) Application.processEvents() installed_books = self._get_cached_books(cached_db) self.installed_books = installed_books
def get_installed_books(self): ''' For each book, construct a BookStruct object with the book's metadata. Starred items are minimally required. BookStruct properties: *active: [True|False] *author: "John Smith" author_sort: (if known) *book_id: an int uniquely identifying the book. Highlights are associated with books through book_id genre: "Fiction" (if known) *reader_app: self.app_name *title: "The Story of John Smith" title_sort: "Story of John Smith, The" (if known) uuid: Calibre's uuid for this book, if known ''' # Sample installed books indexed by book_id dict_of_books = {} dict_of_books[1] = {'author': 'John Smith', 'author_sort': 'Smith, John', 'title': 'The Book by John Smith', 'title_sort': 'Book by John Smith, The'} dict_of_books[2] = {'author': 'William Jones', 'author_sort': 'Jones, William', 'title': 'Learning Programming', 'title_sort': 'Learning Programming'} dict_of_books[3] = {'author': 'Matthew Williams', 'author_sort': 'Williams, Matthew', 'title': 'A Book With No Annotations', 'title_sort': 'Book With No Annotations, A'} self._log("%s:get_installed_books()" % self.app_name) self.installed_books = [] # Don't change the template of books_db string books_db = "%s_books_%s" % (re.sub(' ', '_', self.app_name), re.sub(' ', '_', self.opts.device_name)) installed_books = set([]) # Create the books table self.create_books_table(books_db) # Initialize the progress bar self.opts.pb.set_label("Getting installed books from %s" % self.app_name) self.opts.pb.set_value(0) self.opts.pb.set_maximum(len(dict_of_books)) # Add installed books to the database for book_id in dict_of_books: # Add book_id to list of installed_books (make this a sql function) installed_books.add(book_id) # Populate a BookStruct with available metadata book_mi = BookStruct() # Required items book_mi.active = True book_mi.author = dict_of_books[book_id]['author'] book_mi.book_id = book_id book_mi.reader_app = self.app_name book_mi.title = dict_of_books[book_id]['title'] # Optional items if 'author_sort' in dict_of_books[book_id]: book_mi.author_sort = dict_of_books[book_id]['author_sort'] if 'genre' in dict_of_books[book_id]: book_mi.genre = dict_of_books[book_id]['genre'] if 'title_sort' in dict_of_books[book_id]: book_mi.title_sort = dict_of_books[book_id]['title_sort'] if 'uuid' in dict_of_books[book_id]: book_mi.uuid = dict_of_books[book_id]['uuid'] # Add book to books_db self.add_to_books_db(books_db, book_mi) # Increment the progress bar self.opts.pb.increment() # Update the timestamp self.update_timestamp(books_db) self.commit() self.installed_books = list(installed_books)
def get_installed_books(self): """ Fetch installed books from mainDb.sqlite or cached_db Populate self.tocs: {book_id: {toc_entries} ...} """ self._log("%s:get_installed_books()" % self.app_name) self.opts.pb.set_label("Getting installed books from %s" % self.app_name) self.opts.pb.set_value(0) db_profile = self._localize_database_path(self.app_id, self.books_subpath) self.books_db = db_profile['path'] cached_db = self.generate_books_db_name(self.app_name_, self.ios.device_name) if self.opts.disable_caching or not self._cache_is_current(db_profile['stats'], cached_db): # (Re)load installed books from device self._log(" fetching installed books from %s on %s" % (self.app_name, self.ios.device_name)) # Mount the ios container self.ios.mount_ios_app(app_id=self.app_id) installed_books = set([]) self.tocs = {} # Create the books table as needed self.create_books_table(cached_db) con = sqlite3.connect(self.books_db) with con: con.row_factory = sqlite3.Row cur = con.cursor() cur.execute('''SELECT Author, AuthorSort, Title, CalibreTitleSort, FileName, Books.ID AS id_, UUID FROM Books ''') rows = cur.fetchall() self.opts.pb.set_maximum(len(rows)) for row in rows: self.opts.pb.increment() this_is_news = False path = self._fix_Marvin_path(row[b'FileName']) book_id = row[b'id_'] # Get the genre(s) for this book genre_cur = con.cursor() genre_cur.execute("""SELECT Subject FROM BookSubjects WHERE BookID = '{0}' """.format(book_id)) genres = None genre_rows = genre_cur.fetchall() if genre_rows is not None: genres = ', '.join([genre[b'Subject'] for genre in genre_rows]) genre_cur.close() if 'News' in genres: if not self.collect_news_clippings: continue this_is_news = True installed_books.add(book_id) # Populate a BookStruct b_mi = BookStruct() b_mi.active = True b_mi.author = row[b'Author'] b_mi.author_sort = row[b'AuthorSort'] b_mi.book_id = book_id b_mi.genre = genres b_mi.title = row[b'Title'] b_mi.title_sort = row[b'CalibreTitleSort'] b_mi.uuid = row[b'UUID'] # Add book to books_db self.add_to_books_db(cached_db, b_mi) # Get the library cid, confidence toc_entries = None if this_is_news: cid = self.news_clippings_cid confidence = 5 if path is not None: toc_entries = self._get_epub_toc(path=path, prepend_title=b_mi.title) else: cid, confidence = self.parent.generate_confidence(b_mi) if confidence >= 2: toc_entries = self._get_epub_toc(cid=cid, path=path) elif path is not None: toc_entries = self._get_epub_toc(path=path) self.tocs[book_id] = toc_entries # Update the timestamp self.update_timestamp(cached_db) self.commit() self.ios.disconnect_idevice() installed_books = list(installed_books) else: # Load installed books from cache self._log(" retrieving cached books from %s" % cached_db) self.opts.pb.set_maximum(2) self.opts.pb.set_value(1) Application.processEvents() installed_books = self._get_cached_books(cached_db) self.installed_books = installed_books
def get_installed_books(self): """ Fetch installed books from iBooks_*.sqlite or cache """ self._log("%s:get_installed_books()" % self.app_name) self.opts.pb.set_label("Getting installed books from %s" % self.app_name) self.opts.pb.set_value(0) db_profile = self._localize_database_path(self.app_id, self.books_subpath) self.books_db = db_profile['path'] cached_db = self.generate_books_db_name(self.app_name_, self.ios.device_name) # Test timestamp against cached value if self.opts.disable_caching or not self._cache_is_current(db_profile['stats'], cached_db): # (Re)load installed books from device self._log(" fetching installed books from %s on %s" % (self.app_name, self.ios.device_name)) # Mount the Media folder self.ios.mount_ios_media_folder() installed_books = set([]) self.tocs = {} # Create the books table as needed self.create_books_table(cached_db) con = sqlite3.connect(self.books_db) with con: con.row_factory = sqlite3.Row cur = con.cursor() cur.execute('''SELECT ZASSETURL, ZBOOKAUTHOR, ZSORTAUTHOR, ZBOOKTITLE, ZSORTTITLE, ZDATABASEKEY FROM ZBKBOOKINFO WHERE ZASSETURL LIKE 'file://localhost%' AND ZASSETURL LIKE '%.epub/' ''') rows = cur.fetchall() self.opts.pb.set_maximum(len(rows)) for row in rows: self.opts.pb.increment() this_is_news = False path = self._fix_iBooks_path(row[b'ZASSETURL']) mi = self._get_metadata(path, row[b'ZBOOKTITLE']) genres = mi['genre'].split(', ') if 'News' in genres: if not self.collect_news_clippings: continue this_is_news = True book_id = row[b'ZDATABASEKEY'] installed_books.add(book_id) # Populate a BookStruct b_mi = BookStruct() b_mi.active = True b_mi.author = row[b'ZBOOKAUTHOR'] b_mi.author_sort = row[b'ZSORTAUTHOR'] b_mi.book_id = book_id b_mi.genre = mi['genre'] b_mi.title = row[b'ZBOOKTITLE'] b_mi.title_sort = row[b'ZSORTTITLE'] b_mi.uuid = mi['uuid'] # Add book to books_db self.add_to_books_db(cached_db, b_mi) # Get the library cid, confidence toc_entries = None if this_is_news: cid = self.news_clippings_cid confidence = 5 if path is not None: toc_entries = self._get_epub_toc(path=path, prepend_title=b_mi.title) elif self.ios.exists(path): cid, confidence = self.parent.generate_confidence(b_mi) if confidence >= 2: toc_entries = self._get_epub_toc(cid=cid, path=path) elif path is not None: toc_entries = self._get_epub_toc(path=path) self.tocs[book_id] = toc_entries # Update the timestamp self.update_timestamp(cached_db) self.commit() self.ios.dismount_ios_media_folder() installed_books = list(installed_books) else: self._log(" retrieving cached books from %s" % cached_db) self.opts.pb.set_maximum(2) self.opts.pb.set_value(1) Application.processEvents() installed_books = self._get_cached_books(cached_db) self.installed_books = installed_books